diff --git a/.gitignore b/.gitignore index b39dc026c..57eb2180a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ config/database.yml config/initializers/secret_token.rb config/secrets.yml /storage/ + ## Environment normalisation: /.bundle /vendor/bundle diff --git a/Gemfile b/Gemfile index 459e10e47..d0212b8cd 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,7 @@ gem 'coffee-rails' # Set to 1.8 due to https://github.com/jashkenas/coffeescript/issues/3829 gem 'coffee-script-source', '1.8.0' gem 'devise' +gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14' gem 'fancybox2-rails' gem 'font-awesome-rails' gem 'fullcalendar-rails' @@ -23,7 +24,7 @@ gem 'jbuilder' gem 'jquery-rails' gem 'jquery-turbolinks' gem 'jquery-ui-rails' -gem 'momentjs-rails' +gem 'momentjs-rails', "~> 2.9.0" gem 'mysql2' gem 'paperclip' gem 'prawn-rails' @@ -55,4 +56,3 @@ group :test do gem 'database_cleaner' gem 'shoulda-matchers', require: false end - diff --git a/Gemfile.lock b/Gemfile.lock index 3764770d5..b0ebecbcb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -44,6 +44,8 @@ GEM rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) + bootstrap3-datetimepicker-rails (4.7.14) + momentjs-rails (>= 2.8.1) builder (3.2.2) byebug (4.0.3) columnize (= 0.9.0) @@ -314,6 +316,7 @@ PLATFORMS DEPENDENCIES better_errors + bootstrap3-datetimepicker-rails (~> 4.7.14) cancancan capistrano (~> 3.1.0) capistrano-bundler (~> 1.1.2) @@ -336,7 +339,7 @@ DEPENDENCIES jquery-turbolinks jquery-ui-rails mailcatcher - momentjs-rails + momentjs-rails (~> 2.9.0) mysql2 paperclip poltergeist diff --git a/app/assets/images/border1.png b/app/assets/images/border1.png deleted file mode 100644 index ea73e1592..000000000 Binary files a/app/assets/images/border1.png and /dev/null differ diff --git a/app/assets/images/border2.png b/app/assets/images/border2.png deleted file mode 100644 index 72cad44ce..000000000 Binary files a/app/assets/images/border2.png and /dev/null differ diff --git a/app/assets/images/classic-loader.gif b/app/assets/images/classic-loader.gif deleted file mode 100644 index 27df81f46..000000000 Binary files a/app/assets/images/classic-loader.gif and /dev/null differ diff --git a/app/assets/images/classic-map.png b/app/assets/images/classic-map.png deleted file mode 100644 index fef664f70..000000000 Binary files a/app/assets/images/classic-map.png and /dev/null differ diff --git a/app/assets/images/fullscreen_off.png b/app/assets/images/fullscreen_off.png deleted file mode 100644 index 964a0bc24..000000000 Binary files a/app/assets/images/fullscreen_off.png and /dev/null differ diff --git a/app/assets/images/fullscreen_off.svg b/app/assets/images/fullscreen_off.svg deleted file mode 100644 index 083d8ce91..000000000 --- a/app/assets/images/fullscreen_off.svg +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/app/assets/images/fullscreen_on.png b/app/assets/images/fullscreen_on.png deleted file mode 100644 index 8666b1a91..000000000 Binary files a/app/assets/images/fullscreen_on.png and /dev/null differ diff --git a/app/assets/images/fullscreen_on.svg b/app/assets/images/fullscreen_on.svg deleted file mode 100644 index a2a21bca1..000000000 --- a/app/assets/images/fullscreen_on.svg +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/app/assets/images/hilbert.eps b/app/assets/images/hilbert.eps new file mode 100644 index 000000000..d91a4b68f Binary files /dev/null and b/app/assets/images/hilbert.eps differ diff --git a/app/assets/images/hilbert.jpg b/app/assets/images/hilbert.jpg new file mode 100644 index 000000000..6eee9fd2b Binary files /dev/null and b/app/assets/images/hilbert.jpg differ diff --git a/app/assets/images/pausebutton.png b/app/assets/images/pausebutton.png deleted file mode 100644 index 4efd7f487..000000000 Binary files a/app/assets/images/pausebutton.png and /dev/null differ diff --git a/app/assets/images/pausebutton.svg b/app/assets/images/pausebutton.svg deleted file mode 100644 index d5268036a..000000000 --- a/app/assets/images/pausebutton.svg +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/app/assets/images/playbutton.png b/app/assets/images/playbutton.png deleted file mode 100644 index 6ef916dee..000000000 Binary files a/app/assets/images/playbutton.png and /dev/null differ diff --git a/app/assets/images/playbutton.svg b/app/assets/images/playbutton.svg deleted file mode 100644 index 2c17e1f1c..000000000 --- a/app/assets/images/playbutton.svg +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/app/assets/images/target.png b/app/assets/images/target.png deleted file mode 100644 index 9b5c89611..000000000 Binary files a/app/assets/images/target.png and /dev/null differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 1ceb2408e..6792f541b 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,10 +13,12 @@ //= require jquery //= require jquery.turbolinks //= require jquery_ujs +//= require jquery-ui/effect.all //= require bootstrap //= require_self //= require jquery-ui/datepicker //= require moment +//= require moment/sv //= require fullcalendar //= require fullcalendar/lang/sv.js //= require fancybox @@ -25,3 +27,18 @@ //= require turbolinks //= require gallery_hook.js //= require jquery.countdown +//= require bootstrap-datetimepicker +//= require pickers + +var bottom; +bottom = function () { + var docHeight = $(window).height(); + var footerHeight = $('#copyright').height() + var footerTop = $('#copyright').position().top + footerHeight; + + if (footerTop < docHeight) { + $('#footer').css('margin-top', 22 + (docHeight - footerTop) + 'px'); + } +}; + +$(document).ready(bottom) diff --git a/app/assets/javascripts/cafe_works.js.coffee b/app/assets/javascripts/cafe_works.js.coffee new file mode 100644 index 000000000..1486edb13 --- /dev/null +++ b/app/assets/javascripts/cafe_works.js.coffee @@ -0,0 +1,42 @@ +jQuery -> + $('.datetimepicker').datetimepicker locale: 'sv', format: 'DD/MM/YYYY HH:mm' +jQuery -> + $('#date').datepicker() +jQuery -> + $('#date2').datepicker() +loadCalendar = -> + $('#hilbertkalender').fullCalendar + events: '/hilbertcafe', + weekNumbers: true, + minTime: "08:00:00", + maxTime: "13:00:00", + defaultView: 'agendaWeek', + height: "auto", + weekends: false, + header: { + left: 'prev,next today', + center: 'title', + }, + aspectRatio: 1.3, + weekNumberTitle: "V ", + allDaySlot: false, + slotEventOverlap: false, + eventMouseover: (calEvent, jsEvent) -> + style = 'width:auto;height:auto;background:#eb7125;' + style = style + 'position:absolute;z-index:10001;padding:10px;' + tooltip = '
' + tooltip = tooltip + calEvent.title + tooltip = tooltip + '
' + calEvent.start.format('LLL') + tooltip = tooltip + '
till
' + calEvent.end.format('LLL') + '
' + $('body').append tooltip + $(this).mouseover((e) -> + $(this).css 'z-index', 10000 + $('.tooltipevent').fadeIn '500' + $('.tooltipevent').fadeTo '10', 1.9 + ).mousemove (e) -> + $('.tooltipevent').css 'top', e.pageY + 10 + $('.tooltipevent').css 'left', e.pageX + 20 + eventMouseout: (calEvent, jsEvent) -> + $(this).css 'z-index', 8 + $('.tooltipevent').remove() +$(document).ready(loadCalendar) diff --git a/app/assets/javascripts/election.js.coffee b/app/assets/javascripts/election.js.coffee index 658b9e391..b75529f80 100644 --- a/app/assets/javascripts/election.js.coffee +++ b/app/assets/javascripts/election.js.coffee @@ -1,2 +1,6 @@ $('.collapsing').on 'shown.bs.collapse', -> - $('html,body').animate { scrollTop: $('#views').offset().top }, 'slow' + $('html,body').animate {scrollTop: $('#views').offset().top}, 'slow' + +jQuery -> + $('.datetimepicker1').datetimepicker locale: 'sv', format: 'DD/MM/YYYY HH:mm' + $('.datetimepicker2').datetimepicker locale: 'sv', format: 'DD/MM/YYYY HH:mm' diff --git a/app/assets/javascripts/faq.js.coffee b/app/assets/javascripts/faq.js.coffee deleted file mode 100644 index 24f83d18b..000000000 --- a/app/assets/javascripts/faq.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/menus.js.coffee b/app/assets/javascripts/menus.js.coffee deleted file mode 100644 index 24f83d18b..000000000 --- a/app/assets/javascripts/menus.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.scss similarity index 91% rename from app/assets/stylesheets/application.css rename to app/assets/stylesheets/application.scss index ad962cd7c..7bd08aac3 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.scss @@ -12,6 +12,7 @@ *= require app *= require bootstrap *= require_self + *= require colors *= require style *= require header1 *= require responsive @@ -39,6 +40,13 @@ */ /* Override for Bootstrap 3 font location */ + +// We should eventually import all files like this +@import "colors"; +@import "cafe_works"; +@import "bootstrap"; +@import "bootstrap-datetimepicker"; + @font-face { font-family: 'Glyphicons Halflings'; src: url('../assets/glyphicons-halflings-regular.eot'); diff --git a/app/assets/stylesheets/cafe_works.scss b/app/assets/stylesheets/cafe_works.scss new file mode 100644 index 000000000..7603c3fc3 --- /dev/null +++ b/app/assets/stylesheets/cafe_works.scss @@ -0,0 +1,21 @@ +@import "colors"; + +.cafe-date { + background: $box-color; + border: 2px; + border-color: $border-color; + border-radius: 10px !important; + color: $text-color; + float: center; + height: 85px; + margin: 7px 13px 0 0; + padding: 7px 10px 4px; + width: 100px; + + span { + display: block; + font-size: 20px; + font-weight: 200; + line-height: 25px; + } +} diff --git a/app/assets/stylesheets/colors.scss b/app/assets/stylesheets/colors.scss new file mode 100644 index 000000000..cb95bab37 --- /dev/null +++ b/app/assets/stylesheets/colors.scss @@ -0,0 +1,10 @@ +// See http://sachagreif.com/sass-color-variables + +// Color definitions +$fsek-orange: #eb7125; +$black: #fff; + +// Function definitions +$text-color: $black; +$border-color: $black; +$box-color: $fsek-orange; diff --git a/app/assets/stylesheets/constants.css.scss b/app/assets/stylesheets/constants.scss similarity index 100% rename from app/assets/stylesheets/constants.css.scss rename to app/assets/stylesheets/constants.scss diff --git a/app/assets/stylesheets/custom.css.scss b/app/assets/stylesheets/custom.scss similarity index 100% rename from app/assets/stylesheets/custom.css.scss rename to app/assets/stylesheets/custom.scss diff --git a/app/assets/stylesheets/elections.css.scss b/app/assets/stylesheets/elections.scss similarity index 100% rename from app/assets/stylesheets/elections.css.scss rename to app/assets/stylesheets/elections.scss diff --git a/app/assets/stylesheets/faq.css.scss b/app/assets/stylesheets/faq.scss similarity index 100% rename from app/assets/stylesheets/faq.css.scss rename to app/assets/stylesheets/faq.scss diff --git a/app/assets/stylesheets/fullcalendar-custom.css.scss b/app/assets/stylesheets/fullcalendar-custom.scss similarity index 100% rename from app/assets/stylesheets/fullcalendar-custom.css.scss rename to app/assets/stylesheets/fullcalendar-custom.scss diff --git a/app/assets/stylesheets/gallery.css.scss b/app/assets/stylesheets/gallery.scss similarity index 100% rename from app/assets/stylesheets/gallery.css.scss rename to app/assets/stylesheets/gallery.scss diff --git a/app/assets/stylesheets/menus.css.scss b/app/assets/stylesheets/menus.css.scss deleted file mode 100644 index ee0d72bb6..000000000 --- a/app/assets/stylesheets/menus.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Menus controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/nominations.css.scss b/app/assets/stylesheets/nominations.css.scss deleted file mode 100644 index 99a946f3c..000000000 --- a/app/assets/stylesheets/nominations.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Nominations controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/notices.css.scss b/app/assets/stylesheets/notices.scss similarity index 100% rename from app/assets/stylesheets/notices.css.scss rename to app/assets/stylesheets/notices.scss diff --git a/app/assets/stylesheets/rent.css.scss b/app/assets/stylesheets/rent.scss similarity index 100% rename from app/assets/stylesheets/rent.css.scss rename to app/assets/stylesheets/rent.scss diff --git a/app/assets/stylesheets/scaffolds.css.scss b/app/assets/stylesheets/scaffolds.scss similarity index 100% rename from app/assets/stylesheets/scaffolds.css.scss rename to app/assets/stylesheets/scaffolds.scss diff --git a/app/assets/stylesheets/start_page.css.scss b/app/assets/stylesheets/start_page.scss similarity index 100% rename from app/assets/stylesheets/start_page.css.scss rename to app/assets/stylesheets/start_page.scss diff --git a/app/assets/stylesheets/wice_grid.css.scss b/app/assets/stylesheets/wice_grid.scss similarity index 100% rename from app/assets/stylesheets/wice_grid.css.scss rename to app/assets/stylesheets/wice_grid.scss diff --git a/app/controllers/admin/cafe_works_controller.rb b/app/controllers/admin/cafe_works_controller.rb new file mode 100644 index 000000000..43d1fccf6 --- /dev/null +++ b/app/controllers/admin/cafe_works_controller.rb @@ -0,0 +1,103 @@ +# encoding:UTF-8 +class Admin::CafeWorksController < ApplicationController + load_permissions_and_authorize_resource + before_action :authorize + before_action :set_lv, only: [:setup_create] + before_action :set_new_cafe_work, only: [:setup, :setup_create] + before_action :set_cafe_setup, only: [:setup_create] + + def show + end + + def new + end + + def edit + end + + def create + flash[:notice] = 'Cafejobbet skapades, success.' if @cafe_work.save + redirect_to [:admin, @cafe_work] + end + + def update + if @cafe_work.update(cafe_work_params) + flash[:notice] = 'Cafejobbet uppdaterades' + redirect_to [:admin, @cafe_work] + else + render action: :edit + end + end + + def destroy + # Id used to hide element + @id = @cafe_work.id + @cafe_work.destroy + respond_to do |format| + format.html { redirect_to :admin_hilbert, notice: 'Cafepasset raderades.' } + format.js + end + end + + def remove_worker + if !@cafe_work.clear_worker + render action: show, notice: 'Lyckades inte' + end + end + + def setup + end + + def setup_create + if preview? + @cafe_works = @r.preview(@lv_first, @lv_last) + elsif save? + @r.setup(@lv_first, @lv_last) + flash[:notice] = 'Cafejobben skapades' + end + render :setup + end + + def index + @faqs = Faq.category(:Hilbert).answered + @faq_unanswered = Faq.category(:Hilbert).where(answer: '').count + @cwork_grid = initialize_grid(CafeWork.all) + end + + private + + def authorize + authorize! :manage, CafeWork + end + + def cafe_work_params + params.require(:cafe_work).permit(:work_day, :pass, :lp, :lv) + end + + def set_new_cafe_work + if params[:cafe_work].present? + @cafe_work = CafeWork.new(cafe_work_params) + else + @cafe_work = CafeWork.new + end + end + + def set_cafe_setup + if cafe_work_params[:work_day].present? && cafe_work_params[:lp].present? + @r = CafeSetupWeek.new(Time.zone.parse(cafe_work_params[:work_day]), cafe_work_params[:lp]) + end + end + + def set_lv + @lv_first = (params[:lv_first].present?) ? params[:lv_first].to_i : 0 + @lv_last = (params[:lv_last].present?) ? params[:lv_last].to_i : 0 + end + + def preview? + params[:commit] == 'Förhandsgranska' + end + + def save? + params[:commit] == 'Spara' + end +end diff --git a/app/controllers/admin/elections_controller.rb b/app/controllers/admin/elections_controller.rb index 49d2a45e3..afa4ea202 100644 --- a/app/controllers/admin/elections_controller.rb +++ b/app/controllers/admin/elections_controller.rb @@ -1,75 +1,72 @@ # encoding: UTF-8 class Admin::ElectionsController < ApplicationController - # Quick fix because Cancancan doesn't load when we use URL as param. - # /d.wessman https://github.com/fsek/web/issues/134 + load_permissions_and_authorize_resource find_by: :url before_action :authorize - before_action :set_election, only: [:show,:edit,:update,:destroy,:candidates,:nominations] + before_action :set_posts, only: [:new, :show, :edit] def new - @election = Election.new - @posts = Post.order(title: :asc) end + def show - @posts = Post.order(title: :asc) end + def edit - @posts = Post.order(title: :asc) end + def index @elections = Election.order(start: :desc) end + def create - @election = Election.new(election_params) - respond_to do |format| - if @election.save - format.html { redirect_to [:admin,@election], notice: 'Valet skapades!' } - else - format.html { render action: "new" } - end + if @election.save + redirect_to [:admin, @election], notice: 'Valet skapades' + else + render action: :new end end + def update - respond_to do |format| - if @election.update(election_params) - format.html { redirect_to admin_election_path(@election), notice: 'Valet uppdaterades, gött' } - format.json { head :no_content } - else - format.html { render action: 'edit' } - format.json { render json: @election.errors, status: :unprocessable_entity } - end + if @election.update(election_params) + redirect_to [:admin, @election], notice: 'Valet uppdaterades, gött' + else + render action: :edit end end def destroy @election.destroy - respond_to do |format| - format.html { redirect_to elections_path,notice: 'Valet raderades, hoppas att det var meningen!.' } - format.json { head :no_content } - end + redirect_to admin_elections_path, notice: 'Valet raderades, hoppas att det var meningen!.' end def nominations @nominations_grid = initialize_grid(@election.nominations, - :name => 'g2', - :enable_export_to_csv => true, - :csv_file_name => 'nomineringar') + name: 'g2', + enable_export_to_csv: true, + csv_file_name: 'nomineringar') end + def candidates - @candidates_grid = initialize_grid(@election.candidates,name: "candidates",enable_export_to_csv: true, csv_file_name: 'candidates') + @candidates_grid = initialize_grid(@election.candidates, + name: 'candidates', + enable_export_to_csv: true, + csv_file_name: 'candidates') export_grid_if_requested('g2' => 'nominations_grid') end + private + def authorize - authorize! :manage, @election + authorize! :manage, Election end def election_params - params.fetch(:election).permit(:title,:description,:start,:end,:url,:visible,:mail_link,:mail_styrelse_link,:text_before,:text_during,:text_after,:nominate_mail,:candidate_mail,:extra_text,:candidate_mail_star,:post_ids => []) + params.fetch(:election).permit(:title, :description, :start, :end, :url, + :visible, :mail_link, :mail_styrelse_link, :text_before, + :text_during, :text_after, :nominate_mail, :candidate_mail, + :extra_text, :candidate_mail_star, post_ids: []) end - def set_election - @election = Election.find_by_url(params[:id]) - if(!@election.instance_of?(Election)) - redirect_to action: :index - end + + def set_posts + @posts = Post.all end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ac52ebc51..b06929fd4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,8 +2,8 @@ class ApplicationController < ActionController::Base protect_from_forgery - before_filter :configure_permitted_devise_parameters, if: :devise_controller? - before_filter :set_locale + before_action :configure_permitted_devise_parameters, if: :devise_controller? + before_action :set_locale rescue_from CanCan::AccessDenied do |ex| flash[:error] = ex.message @@ -12,7 +12,7 @@ class ApplicationController < ActionController::Base rescue_from ActiveRecord::RecordInvalid do |ex| flash[:error] = - "Fel i formulär: #{ex.record.errors.full_messages.join '; '}" + "Fel i formulär: #{ex.record.errors.full_messages.join '; '}" render referring_action, status: :unprocessable_entity end @@ -24,9 +24,15 @@ class ApplicationController < ActionController::Base protected def configure_permitted_devise_parameters - devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :password, :remember_me) } - devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) } - devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:password, :password_confirmation, :current_password) } + devise_parameter_sanitizer.for(:sign_in) do |u| + u.permit(:username, :password, :remember_me) + end + devise_parameter_sanitizer.for(:sign_up) do |u| + u.permit(:username, :email, :password, :password_confirmation) + end + devise_parameter_sanitizer.for(:account_update) do |u| + u.permit(:password, :password_confirmation, :current_password) + end end def self.permission @@ -48,7 +54,7 @@ def load_permissions # Enables authentication and def self.load_permissions_and_authorize_resource(*args) load_and_authorize_resource(*args) - before_filter(:load_permissions, *args) + before_action(:load_permissions, *args) end def self.skip_authorization(*args) @@ -72,7 +78,6 @@ def set_locale locale = lang if langs.include? lang end end - I18n.locale = locale redirect_to(:back) if params[:locale] end diff --git a/app/controllers/cafe_works_controller.rb b/app/controllers/cafe_works_controller.rb new file mode 100644 index 000000000..8ea976a7b --- /dev/null +++ b/app/controllers/cafe_works_controller.rb @@ -0,0 +1,62 @@ +# encoding:UTF-8 +class CafeWorksController < ApplicationController + load_permissions_and_authorize_resource + before_action :councils, except: [:index, :nyckelpiga] + before_action :set_faqs, only: :index + + def show + @cafe_work.load(current_user) + end + + def authorize + @authenticated = @cafe_work.authorize(worker_params[:access_code]) + end + + def update_worker + if @cafe_work.add_or_update(worker_params, current_user) + flash[:notice] = 'Bokningen uppdaterades - du arbetar!' + redirect_to @cafe_work + else + render action: :show + end + end + + def remove_worker + access = (params[:cafe_work].present?) ? worker_params[:access_code] : nil + if @cafe_work.remove_worker(current_user, access) + flash[:notice] = 'Du arbetar inte längre på passet' + redirect_to @cafe_work + else + render action: :show + end + end + + def index + respond_to do |format| + format.html { @lv = CafeWork.get_lv } + format.json { render json: CafeWork.between(params[:start], params[:end]) } + end + end + + def nyckelpiga + authorize! :nyckelpiga, CafeWork + @date = (params[:date].present?) ? Time.zone.parse(params[:date]) : Time.zone.now + @work_grid = initialize_grid(CafeWork.between(@date.beginning_of_day, + @date.end_of_day).ascending) + end + + private + + def worker_params + params.require(:cafe_work).permit(:profile_id, :name, :lastname, :phone, :email, + :utskottskamp, :access_code, council_ids: []) + end + + def councils + @councils = Council.all + end + + def set_faqs + @faqs = Faq.category(:Hilbert).answered + end +end diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index fbf80a28c..2a7a054da 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -1,44 +1,37 @@ # encoding:UTF-8 class ContactsController < ApplicationController - before_filter :authenticate_edit, only: [:new,:edit,:update,:destroy] - before_action :set_contact, only: [:show, :edit,:update,:destroy,:mail] + before_filter :authenticate_edit, only: [:new, :edit, :update, :destroy] + before_action :set_contact, only: [:show, :edit, :update, :destroy, :mail] - # GET /councils - # GET /councils.json def index @contacts = Contact.all end - # GET /councils/1 - # GET /councils/1.json def show @sent = false end - # GET /councils/new def new @contact = Contact.new end - # GET /councils/1/edit def edit end - def mail - if(params[:name]) && (params[:email]) && (params[:msg]) + + def mail + if (params[:name]) && (params[:email]) && (params[:msg]) @name = params[:name] @email = params[:email] @msg = params[:msg] - ContactMailer.contact_email(@name,@email,@msg,@contact).deliver + ContactMailer.contact_email(@name, @email, @msg, @contact).deliver_now respond_to do |format| format.html { redirect_to @contact, notice: 'Meddelandet skickades.' } format.json { render action: 'show', status: :created, location: @contact } @sent = true end - end + end end - # POST /councils - # POST /councils.json def create @contact = Contact.new(contact_params) respond_to do |format| @@ -52,12 +45,10 @@ def create end end - # PATCH/PUT /councils/1 - # PATCH/PUT /councils/1.json def update respond_to do |format| if @contact.update(contact_params) - format.html { render action: 'edit' , notice: 'Kontakten uppdaterades!' } + format.html { render action: 'edit', notice: 'Kontakten uppdaterades!' } format.json { head :no_content } else format.html { render action: 'edit' } @@ -66,8 +57,6 @@ def update end end - # DELETE /councils/1 - # DELETE /councils/1.json def destroy @contact.destroy respond_to do |format| @@ -77,22 +66,16 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_contact - @contact = Contact.find_by_id(params[:id]) - if(@contact == nil) - redirect_to(contacts_path,notice: 'Ingen kontakt hittades.') - end - end - def authenticate_edit - - redirect_to(:back) unless current_user.moderator?(:kontakt) - - rescue ActionController::RedirectBackError - redirect_to root_path + # Use callbacks to share common setup or constraints between actions. + def set_contact + @contact = Contact.find_by_id(params[:id]) + if (@contact == nil) + redirect_to(contacts_path, notice: 'Ingen kontakt hittades.') end - # Never trust parameters from the scary internet, only allow the white list through. - def contact_params - params.require(:contact).permit(:name,:email,:public,:text,:council_id) - end + end + + # Never trust parameters from the scary internet, only allow the white list through. + def contact_params + params.require(:contact).permit(:name, :email, :public, :text, :council_id) + end end diff --git a/app/controllers/councils_controller.rb b/app/controllers/councils_controller.rb index 182fedb5d..bcd4da06b 100644 --- a/app/controllers/councils_controller.rb +++ b/app/controllers/councils_controller.rb @@ -1,82 +1,54 @@ # encoding:UTF-8 class CouncilsController < ApplicationController - load_permissions_and_authorize_resource - before_action :set_council, only: [:show, :edit, :update, :destroy] + load_permissions_and_authorize_resource find_by: :url + before_action :set_page, only: :show before_action :set_councils - # GET /councils - # GET /councils.json def index end - # GET /councils/1 - # GET /councils/1.json def show if @page - @mainelements = @page.page_elements.where(visible: true, sidebar: false) - @sidebarelements = @page.page_elements.where(visible: true, sidebar: true) - if @mainelements.count > 1 - @mainelements = @mainelements.sort_by { |x| x[:displayIndex] } - end + @mainelements = @page.page_elements.where(visible: true, + sidebar: false).order(:displayIndex, :asc) + @sidebarelements = @page.page_elements.where(visible: true, + sidebar: true).order(:displayIndex, :asc) end @poster = @council.posts end - # GET /councils/new def new - @council = Council.new end - # GET /councils/1/edit def edit - @contact = Contact.all.where(council_id: @council.id).first - if not @contact - @contact = Contact.new - @contact.council_id = @council.id - @contact.save - end + @contact = Contact.where(council_id: @council.id).first end - # POST /councils def create - @council = Council.new(council_params) - @council.build_page(council_id: @council.id) if @council.save + @council.build_page!(council_id: @council.id) redirect_to edit_council_path(@council), notice: 'Utskott skapades, success.' else render action: 'new' end end - # PATCH/PUT /councils/1 - # PATCH/PUT /councils/1.json def update - respond_to do |format| - if @council.update(council_params) - format.html { redirect_to edit_council_path(@council), notice: 'Utskott uppdaterades!' } - format.json { head :no_content } - else - format.html { render action: 'edit' } - format.json { render json: @council.errors, status: :unprocessable_entity } - end + if @council.update(council_params) + redirect_to edit_council_path(@council), notice: 'Utskott uppdaterades!' + else + render action: :edit end end - # DELETE /councils/1 - # DELETE /councils/1.json def destroy @council.destroy - respond_to do |format| - format.html { redirect_to councils_url } - format.json { head :no_content } - end + redirect_to councils_url, notice: 'Utskottet raderades' end private - # Use callbacks to share common setup or constraints between actions. - def set_council - @council = Council.find_by_id(params[:id]) + def set_page @page = @council.page end @@ -84,8 +56,8 @@ def set_councils @councils = Council.all end - # Never trust parameters from the scary internet, only allow the white list through. def council_params - params.require(:council).permit(:title, :url, :description, :president, :vicepresident, :public) + params.require(:council).permit(:title, :url, :description, + :president, :vicepresident, :public) end end diff --git a/app/controllers/election/candidates_controller.rb b/app/controllers/election/candidates_controller.rb index e9a73d649..296955afc 100644 --- a/app/controllers/election/candidates_controller.rb +++ b/app/controllers/election/candidates_controller.rb @@ -1,11 +1,9 @@ # encoding: UTF-8 class Election::CandidatesController < ApplicationController - load_permissions_and_authorize_resource before_action :set_election - before_action :set_candidate, only: [:show, :update, :destroy] + load_permissions_and_authorize_resource respond_to :html - def index @candidates = current_user.profile.candidates.where(election: @election) @candidates_grid = initialize_grid(@candidates) diff --git a/app/controllers/election/nominations_controller.rb b/app/controllers/election/nominations_controller.rb index 8fd79d81f..2b47dbc23 100644 --- a/app/controllers/election/nominations_controller.rb +++ b/app/controllers/election/nominations_controller.rb @@ -1,7 +1,8 @@ # encoding: UTF-8 class Election::NominationsController < ApplicationController - load_permissions_and_authorize_resource before_action :set_election + load_permissions_and_authorize_resource + def new @nomination = @election.nominations.new() if params[:post].present? @@ -11,17 +12,18 @@ def new def create @nomination = @election.nominations.build(nomination_params) - if @nomination.save - @saved = true - # Background job send_mail - # ElectionMailer.nominate_email(@nomination).deliver - end + @saved = @nomination.save end + private def set_election @election = Election.current + if @election.nil? + redirect_to elections_path + end end + def nomination_params - params.require(:nomination).permit(:name,:email,:motivation,:post_id) + params.require(:nomination).permit(:name, :email, :motivation, :post_id) end end diff --git a/app/controllers/elections_controller.rb b/app/controllers/elections_controller.rb index 7968d7f97..65d1feb4b 100644 --- a/app/controllers/elections_controller.rb +++ b/app/controllers/elections_controller.rb @@ -1,21 +1,20 @@ # encoding:UTF-8 class ElectionsController < ApplicationController + before_action :set_election load_permissions_and_authorize_resource - before_filter :no_election, only: [:nominate,:create_nomination,:candidate] - + def index - @election = Election.current - if(@election.instance_of?(Election)) - @grid_election = initialize_grid(@election.current_posts, name: "election") - @grid_termins = initialize_grid(@election.posts.termins, name: "election") + if @election.instance_of?(Election) + @grid_election = initialize_grid(@election.current_posts, name: 'election') + @grid_termins = initialize_grid(@election.posts.termins, name: 'election') else @election = nil - end + end end + private -private - def election_params - params.fetch(:election).permit(:title,:description,:start,:end,:url,:visible,:mail_link,:mail_styrelse_link,:text_before,:text_during,:text_after,:nominate_mail,:candidate_mail,:extra_text,:candidate_mail_star,:post_ids => []) + def set_election + @election = Election.current end end diff --git a/app/controllers/faqs_controller.rb b/app/controllers/faqs_controller.rb index 96b27791a..ed2787f71 100644 --- a/app/controllers/faqs_controller.rb +++ b/app/controllers/faqs_controller.rb @@ -1,18 +1,15 @@ # encoding:UTF-8 class FaqsController < ApplicationController - before_filter :authenticate_editor, only: [:edit,:update,:destroy] + before_action :authenticate_editor, only: [:edit, :update, :destroy] before_action :set_editor, only: [:new, :show, :edit, :index] before_action :set_faq, only: [:show, :edit, :update, :destroy] - def index @faq = Faq.where.not(answer: '').where(category: 'main') - @faq_hilbert = Faq.where.not(answer: '').where(category: 'Hilbert') if @editor - @faq_unanswered = Faq.where(answer: '',category: 'main') - @hilbert_unanswered = Faq.where(answer: '', category: 'Hilbert') + @faq_unanswered = Faq.where(answer: '', category: 'main') end end @@ -21,7 +18,7 @@ def show def new @faq = Faq.new - if(params[:category]) + if params[:category].present? @faq.category = params[:category] end end @@ -86,7 +83,7 @@ def set_editor end def faq_params - params.require(:faq).permit(:question, :answer,:category) + params.require(:faq).permit(:question, :answer, :category) end -end \ No newline at end of file +end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 916f1f634..988c4acb2 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -2,15 +2,15 @@ class PostsController < ApplicationController load_permissions_and_authorize_resource before_action :set_council - before_action :set_post, only: [:show, :edit, :update, :destroy, :remove_profile,:add_profile_username, :display] def remove_profile @profile = Profile.find_by_id(params[:profile_id]) - @post.profiles.delete(@profile) + @post.profiles.delete(@profile) respond_to do |format| - format.html { redirect_to council_posts_path(@council), notice: @profile.name.to_s + ' har inte längre posten ' + @post.title.to_s + '.'} - end + format.html { redirect_to council_posts_path(@council), notice: @profile.name.to_s + ' har inte längre posten ' + @post.title.to_s + '.' } + end end + def add_profile_username @user = User.find_by(username: params[:username]) if @user != nil @@ -18,53 +18,48 @@ def add_profile_username end if @profile == nil respond_to do |format| - format.html { redirect_to council_posts_path(@council), flash: {alert: 'Hittade ingen användare med det användarnamnet.'}} + format.html { redirect_to council_posts_path(@council), flash: {alert: 'Hittade ingen användare med det användarnamnet.'} } end - elsif @profile.name.blank? - redirect_to council_posts_path(@council), flash: {alert: 'Användaren :"' + @user.username.to_s + '" måste fylla i fler uppgifter i sin profil.'} + elsif @profile.name.blank? + redirect_to council_posts_path(@council), flash: {alert: 'Användaren :"' + @user.username.to_s + '" måste fylla i fler uppgifter i sin profil.'} elsif @profile.posts.include?(@post) - redirect_to council_posts_path(@council), flash: {alert: @profile.name.to_s + '(' + @user.username.to_s + ') har redan posten '+@post.title.to_s + '.'} + redirect_to council_posts_path(@council), flash: {alert: @profile.name.to_s + '(' + @user.username.to_s + ') har redan posten '+@post.title.to_s + '.'} elsif (@post.limit != nil) && (@post.profiles.size >= @post.limit) - redirect_to council_posts_path(@council), flash: {alert: @post.title.to_s + ' har sitt maxantal.'} - else - @post.profiles << @profile + redirect_to council_posts_path(@council), flash: {alert: @post.title.to_s + ' har sitt maxantal.'} + else + @post.profiles << @profile redirect_to council_posts_path(@council), notice: @profile.name.to_s + ' (' + @profile.user.username.to_s + ') tilldelades posten '+@post.title.to_s + '.' - if (@profile.first_post == nil) + if (@profile.first_post == nil) @profile.update(first_post: @post.id) - end + end end end - - def index - if(@council) + def index + if (@council) @posts = @council.posts else @posts = Post.all end - @post_grid = initialize_grid(@posts) + @post_grid = initialize_grid(@posts) end - # GET /news/new def new @post = @council.posts.build @councils = Council.order(title: :asc) end - # GET /news/1/edit def edit - @post_permissions = @post.permissions.collect!{|p| p.id} + @post_permissions = @post.permissions.collect! { |p| p.id } @councils = Council.order(title: :asc) @permissions = Permission.all end - # POST /news - # POST /news.json def create @councils = Council.order(title: :asc) - @post = @council.posts.build(post_params) + @post = @council.posts.build(post_params) respond_to do |format| - if @post.save + if @post.save format.html { redirect_to council_posts_path(@council), notice: 'Posten skapades!' } format.json { render action: 'show', status: :created, location: @post } else @@ -74,20 +69,18 @@ def create end end - # PATCH/PUT /news/1 - # PATCH/PUT /news/1.json - def update + def update respond_to do |format| @post.attributes = post_params @post.permissions = [] @post.set_permissions(params[:permissions]) if params[:permissions] if @post.save @council2 = Council.find_by_id(params[:post][:council]) - if(@council2) && (@council2.equal?(@council) == false) + if (@council2) && (@council2.equal?(@council) == false) @council2.posts << @post - @council = @council2 - end - format.html { redirect_to edit_council_post_path(@council,@post), notice: 'Posten uppdaterades!' } + @council = @council2 + end + format.html { redirect_to edit_council_post_path(@council, @post), notice: 'Posten uppdaterades!' } format.json { head :no_content } else @councils = Council.order(title: :asc) @@ -97,8 +90,6 @@ def update end end - # DELETE /news/1 - # DELETE /news/1.json def destroy @post.profiles.clear @post.destroy @@ -115,15 +106,15 @@ def collapse end private + def post_params - params.require(:post).permit(:title, :limit,:recLimit,:description,:elected_by,:elected_at,:styrelse,:car_rent,:council_id,:permissions) + params.require(:post).permit(:title, :limit, :recLimit, + :description, :elected_by, :elected_at, + :styrelse, :car_rent, :council_id, :permissions) end - # Use callbacks to share common setup or constraints between actions. - def set_post - @post = Post.find(params[:id]) - end - def set_council - @council = Council.find_by_id(params[:council_id]) + + def set_council + @council = Council.find_by_url(params[:council_id]) end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 5b79a1b6f..5d9a32013 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,8 +1,6 @@ # encoding:UTF-8 class ProfilesController < ApplicationController - #load_permissions_and_authorize_resource - - before_action :set_profile, only: [:show, :edit, :update,:remove_post, :avatar] + load_permissions_and_authorize_resource def show if (@profile.owner?(current_user)) && (@profile.fresh?) diff --git a/app/controllers/rents_controller.rb b/app/controllers/rents_controller.rb index 9450830ff..3ba5ff98f 100644 --- a/app/controllers/rents_controller.rb +++ b/app/controllers/rents_controller.rb @@ -1,5 +1,6 @@ # encoding:UTF-8 class RentsController < ApplicationController + load_permissions_and_authorize_resource before_action :set_rents, only: [:new, :edit, :create, :update, :authorize] before_action :set_rent, only: [:show, :edit, :update, :authorize] respond_to :html, :json diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index b67a00443..3be5b6c1b 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -15,5 +15,3 @@ def index end end end - - diff --git a/app/mailers/cafe_mailer.rb b/app/mailers/cafe_mailer.rb new file mode 100644 index 000000000..368f83d29 --- /dev/null +++ b/app/mailers/cafe_mailer.rb @@ -0,0 +1,20 @@ +# encoding: UTF-8 +class CafeMailer < ActionMailer::Base + before_action :load_hilbert + default from: '"Cafemästarna" ' + + def sign_up_email(cafe_work) + @cafe_work = cafe_work + if (@cafe_work) && (@cafe_work.email.present?) + mail to: @cafe_work.assignee.p_email, + subject: %(Hilbert Café: jobba den #{@cafe_work.print_date} (fsektionen.se)), + sent_on: Time.zone.now + end + end + + private + + def load_hilbert + attachments.inline['hilbert.jpg'] = File.read(Rails.root.join('app/assets/images/hilbert.jpg')) + end +end diff --git a/app/mailers/contact_mailer.rb b/app/mailers/contact_mailer.rb index 0c0407aec..c744bf833 100644 --- a/app/mailers/contact_mailer.rb +++ b/app/mailers/contact_mailer.rb @@ -2,14 +2,14 @@ class ContactMailer < ActionMailer::Base default from: 'Spindelman ', parts_order: ["text/plain", "text/html"] default subject: 'Meddelande via Fsektionen.se' - - def contact_email(name,email,msg,kontakt) - @name = name - @email = email - @msg = msg - @kontakt = kontakt - if(@name) && (@email) && (@msg) && (@kontakt) + + def contact_email(name, email, msg, kontakt) + @name = name + @email = email + @msg = msg + @kontakt = kontakt + if (@name) && (@email) && (@msg) && (@kontakt) mail from: @name + ' <'+@email+'>', to: @kontakt.email - end + end end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 8639836b4..ce5a8cfb1 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -10,14 +10,25 @@ def initialize(user) can :read, News can :read, Council can :read, Election + can :read, Document, public: true + + # TODO Should be removed when everyone is required to log in. + # /d.wessman 2015-03-28 + can [:read, :update_worker, :remove_worker, :authorize], CafeWork + can [:read, :main], Rent # Abilities all signed in users get if user.id + can :nominate, Election + can :candidate, Election + can :manage, Candidate, profile_id: user.profile.id + can :manage, Profile, user_id: user.id can :read, Post can :read, Document can :read, :old_gallery can :read, Event - # We really need to move calendar to its own controller + + # TODO We really need to move calendar to its own controller can :calendar, Event end @@ -27,7 +38,7 @@ def initialize(user) user.profile.posts.each do |post| post.permissions.each do |permission| if permission.subject_class == 'all' - can permission.action.to_sym, permission.subject_class.to_sym + can permission.action.to_sym, :all else can permission.action.to_sym, permission.subject_class.constantize end diff --git a/app/models/assignee.rb b/app/models/assignee.rb new file mode 100644 index 000000000..16c896161 --- /dev/null +++ b/app/models/assignee.rb @@ -0,0 +1,106 @@ +# encoding: UTF-8 + +# An assignee describes a user and have some common attributes. +# The assignee is used as a Value Object, and is not saved with ActiveRecord. +# For example - see implementation in CafeWork model. +# An assignee can only be created with Assignee.new(param_hash), not create. +# You cannot save values here, that belongs in the ActiveRecord model. +# Ref: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ +# /d.wessman +class Assignee + include ActiveModel::Model + + # Attributes that can be set and be read. + attr_accessor :name, :lastname, :phone, :email, :profile_id, :access_code, :profile + + # Method used to setup new Assignee with a user > profile/access_code + # User present > Profile is set to User.profile + # User absent > Access Code is generated + def self.setup(assignee_params, user) + new(assignee_params).prepare(user) + end + + # To define if the Assignee is set and present. + def present? + has_profile? || has_access_code? + end + + # Printing methods + def p_name + %(#{name} #{lastname}) + end + + # Can be used in mailer, will generate proper tag. + def p_email + %("#{name} #{lastname}" <#{email}>) + end + + # A way to clear all the attributes of the Assignee + # Returns array of attributes, this way it can be used like: + # Model.attributes = assignee.clear_attributes + # Which saves a lot of rows and declarations. + def clear_attributes + self.name, self.lastname, self.phone = nil, nil, nil + self.email, self.profile_id, self.access_code = nil, nil, nil + attributes + end + + def load_profile(user) + if (user.present?) && !has_profile? + self.name, self.lastname = user.profile.name, user.profile.lastname + self.email,self.phone = user.profile.email, user.profile.phone + end + attributes + end + + # Returns a hash of the current attributes + def attributes + { + name: name, lastname: lastname, email: email, + phone: phone, profile_id: profile_id, access_code: access_code + } + end + + # Method to return the profile. + # The @profile variable is set if a profile is sent in with the parameter hash. + def profile + @profile || Profile.find_by_id(profile_id) + end + + def has_profile? + profile.present? + end + + def has_access_code? + access_code.present? + end + + def equals?(assignee) + name == assignee.name && + lastname == assignee.lastname && + email == assignee.email && + phone == assignee.phone + end + + # For custom creation action where parameters is set and + # profile or access_code setup is made. + def prepare(user) + set_profile(user) + set_access_code + self + end + + protected + + def set_profile(user) + if !has_profile? && user.present? + self.profile_id = (@profile = user.profile).id + end + end + + def set_access_code + if !has_profile? && !has_access_code? + self.access_code = (0...15).map { (65 + rand(26)).chr }.join.to_s + end + end +end diff --git a/app/models/cafe_work.rb b/app/models/cafe_work.rb new file mode 100644 index 000000000..a4a631e56 --- /dev/null +++ b/app/models/cafe_work.rb @@ -0,0 +1,249 @@ +# encoding: UTF-8 +class CafeWork < ActiveRecord::Base + # Associations + belongs_to :profile + has_many :councils, through: :cafe_work_councils + has_many :cafe_work_councils + + # Validations + validates :work_day, :pass, :lp, :lv, presence: true + validates :pass, :lp, inclusion: { in: 1..4 } + validates :lv, inclusion: { in: 1..7 } + validates :name, :lastname, :phone, :email, presence: true, if: :has_worker? + validates :pass, uniqueness: { scope: [:work_day, :lv, :lp, :d_year] } + + # Scopes + scope :with_worker, -> { where('profile_id IS NOT null OR access_code IS NOT null') } + scope :between, ->(from, to) { where(work_day: from..to) } + scope :ascending, -> { order(pass: :asc) } + scope :week, ->(week) { where(lv: week) } + scope :period, ->(p) { where(lp: p) } + scope :year, ->(y) { where(d_year: y) } + + after_update :send_email, if: :has_worker? + + # A custom class for the worker + # For more information see Assignee model or + # read comments above methods + def worker + @worker || Assignee.new(worker_attributes) + end + + # Sends email to worker + # /d.wessman + def send_email + CafeMailer.sign_up_email(self).deliver_now + rescue + Rails.logger.info 'Mailer could not connect, rescued here' + end + + # Prepares work for a user to sign up, without saving + # Will only change attributes if there is no worker and + # user is present. + # /d.wessman + def load(user) + self.attributes = worker.load_profile(user) + end + + # Shows different status texts depending on the user. + # /d.wessman + def status_text(user) + case status_view(user) + when :sign_up + return 'Fyll i uppgifter och tryck på Spara för att skriva upp dig och arbeta på passet.' + when :edit + return 'Du är uppskriven för att arbeta på passet.' + when :assigned + return 'Passet är redan bokat.' + when :authorize + return 'Passet är bokat, fyll i koden som mailades ut vid anmälan för att redigera.' + end + end + + # Gives different statuses for the view + # 0 = everyone can sign up + # 1 = can be edited, either logged in or authorized + # 2 = shows no form + # 3 = shows form for authorization + # /d.wessman + def status_view(user) + if access_code.present? + return :authorize + elsif has_worker? + return owner?(user) ? :edit : :assigned + end + :sign_up + end + + def add_or_update(worker_params, user) + if has_worker? + update_worker(worker_params, user) + else + add_worker(worker_params, user) + end + end + + # User to update worker, checks for edit-access and triggers at_update + # /d.wessman + def add_worker(worker_params, user) + if has_worker? + errors.add('Arbetare', 'passet har redan en.') + return false + end + + # Should be done with a bang when the error handling works + # Ref: https://github.com/fsek/web/issues/93 + # /d.wessman + self.attributes = worker_params + self.attributes = Assignee.setup(worker_attributes, user).attributes + save + end + + # User to update worker, checks for edit-access + # /d.wessman + def update_worker(worker_params, user) + if !owner?(user) && !authorize(worker_params[:access_code]) + errors.add('Auktorisering', + 'misslyckades, du har inte rättighet att redigera eller skrev fel kod.') + return false + end + + # Should be done with a bang when the error handling works + # Ref: https://github.com/fsek/web/issues/93 + # /d.wessman + self.attributes = worker_params + self.attributes = Assignee.setup(worker_attributes, user).attributes + save + end + + # Remove-function used by the worker + # /d.wessman + def remove_worker(user, access) + if !owner?(user) && !authorize(access) + errors.add('Auktorisering', + 'misslyckades, du har inte rättighet att ta bort eller skrev fel kod.') + return false + end + + clear_worker + end + + # Method to remove the worker from current work. + # /d.wessman + def clear_worker + self.attributes = worker.clear_attributes + self.utskottskamp = false + councils.clear + self.save!(validate: false) + end + + # Returns true if the profiles are similar and not nil + # /d.wessman + def owner?(user) + user.present? && user.profile.present? && profile.present? && user.profile == profile + end + + # Returns true if the user can edit the object + # /d.wessman + def edit?(user) + editable? && (!has_worker? || owner?(user)) + end + + def editable? + work_day > Time.zone.now + end + + # Returns true only if the access_code is correct + # /d.wessman + def authorize(access) + access.present? && access_code.present? && access_code == access + end + + # Returns true if there is a worker + # /d.wessman + def has_worker? + worker.present? + end + + # Used to print date in a usable format. + # /d.wessman + def print_time + %(#{start.strftime('%H:%M')}-#{stop.strftime('%H:%M')}) + end + + # Used to print out date, reading week and work number + # /d.wessman + def print + %(#{print_date} LV: #{lv} Pass: #{pass}) + end + + def print_date + %(#{print_time}, #{start.strftime('%A %d/%m')}) + end + + # Prints the url or path for the current object + def p_url + Rails.application.routes.url_helpers.cafe_work_url(id, host: PUBLIC_URL) + end + + def p_path + Rails.application.routes.url_helpers.cafe_work_path(id) + end + + def as_json(*) + { + id: id, + title: %(Cafepass #{pass}), + start: start.iso8601, + end: stop.iso8601, + status: print, + url: p_path, + color: 'black', + backgroundColor: b_color, + textColor: 'black' + } + end + + # To print start time + def t_start + start.strftime('%H:%M') + end + + # To print end time + def t_end + stop.strftime('%H:%M') + end + + def start + work_day + end + + # End would be a better name, doesn't fit into code. + def stop + work_day + duration.hours + end + + def self.get_lv + check = CafeWork.between(Time.zone.now.beginning_of_day - 2.days, Time.zone.now.end_of_day).last + (check.present?) ? check.lv.to_s : '?' + end + + protected + + def worker_attributes + { + name: name, lastname: lastname, email: email, + phone: phone, profile: profile, profile_id: profile_id, access_code: access_code + } + end + + # Background color for the event + def b_color + (has_worker?) ? 'orange' : 'white' + end + + # Duration of work + def duration + ((pass == 1) || (pass == 2)) ? 2 : 3 + end +end diff --git a/app/models/cafe_work_council.rb b/app/models/cafe_work_council.rb new file mode 100644 index 000000000..85cad7491 --- /dev/null +++ b/app/models/cafe_work_council.rb @@ -0,0 +1,6 @@ +class CafeWorkCouncil < ActiveRecord::Base + belongs_to :cafe_work + belongs_to :council + + validates :cafe_work, :council, presence: true +end diff --git a/app/models/cafetimmar.rb b/app/models/cafetimmar.rb deleted file mode 100644 index bff7e4811..000000000 --- a/app/models/cafetimmar.rb +++ /dev/null @@ -1,17 +0,0 @@ -# encoding: UTF-8 -class Cafetimmar < ActiveRecord::Base - - def ical - e=Icalendar::Event.new - e.uid=self.id - e.dtstart=DateTime.civil(self.date.year, self.date.month, self.date.day, self.date.hour, self.date.min) - e.dtend=DateTime.civil(self.end_date.year, self.end_date.month, self.end_date.day, self.end_date.hour, self.end_date.min) - e.location = self.location - e.summary=self.title - e.description = self.content - e.created=self.created_at - e.url= "#{PUBLIC_URL}/events/#{self.id}" - e.last_modified=self.updated_at - e - end -end diff --git a/app/models/candidate.rb b/app/models/candidate.rb index 23a9e0cbe..1e2e9d516 100644 --- a/app/models/candidate.rb +++ b/app/models/candidate.rb @@ -1,9 +1,11 @@ # encoding: UTF-8 class Candidate < ActiveRecord::Base + # Associations belongs_to :election belongs_to :profile belongs_to :post + # Validations validates :profile_id, uniqueness: { scope: [:post_id, :election_id], message: 'har redan en likadan kandidatur' }, on: :create @@ -28,6 +30,18 @@ def prepare(user) end end + def editable? + election.view_status == 2 || post.elected_by == 'Studierådet' + end + + def p_url + Rails.application.routes.url_helpers.election_candidate_url(id, host: PUBLIC_URL) + end + + def p_path + Rails.application.routes.url_helpers.election_candidate_path(id) + end + def owner?(user) user.present? && user.profile == profile end diff --git a/app/models/constant.rb b/app/models/constant.rb index 21789d596..238aa6109 100644 --- a/app/models/constant.rb +++ b/app/models/constant.rb @@ -1,6 +1,7 @@ class Constant < ActiveRecord::Base - validates :name, presence: true, uniqueness: true - validates :value, presence: true + # Validations + validates :name, :value, presence: true + validates :name, uniqueness: true def self.get(name) c = Constant.where(name: name).first diff --git a/app/models/council.rb b/app/models/council.rb index b3a0d184f..bb9777431 100644 --- a/app/models/council.rb +++ b/app/models/council.rb @@ -1,15 +1,34 @@ # encoding: UTF-8 class Council < ActiveRecord::Base + # Associations has_one :page, dependent: :destroy + belongs_to :president, foreign_key: :president, class_name: :Post belongs_to :vice_president, foreign_key: :vice_president, class_name: :Post + has_many :posts has_many :profiles, through: :posts + has_many :cafe_work_councils + has_many :cafe_works, through: :cafe_work_councils - validates :title,:url,:presence => true + # Validation + validates :title, :url, presence: true validates :url, uniqueness: true def to_s - self.title + title + end + + # To use the url as actual url + def to_param + (url.present?) ? url : id + end + + def p_url + Rails.application.routes.url_helpers.council_url(id, host: PUBLIC_URL) + end + + def p_path + Rails.application.routes.url_helpers.council_path(id) end end diff --git a/app/models/election.rb b/app/models/election.rb index 11ac3dac4..0fa742c7c 100644 --- a/app/models/election.rb +++ b/app/models/election.rb @@ -4,10 +4,11 @@ class Election < ActiveRecord::Base has_many :candidates, dependent: :destroy has_and_belongs_to_many :posts - validates_presence_of :url - validates_uniqueness_of :url - - scope :current, -> { order(start: :asc).where(visible: true).take } + validates :url, presence: true, uniqueness: true + + def self.current + self.order(start: :asc).where(visible: true).first || nil + end # Returns a number to load different views # 1: before the election opens diff --git a/app/models/news.rb b/app/models/news.rb index 14b80349a..9fd1441fe 100644 --- a/app/models/news.rb +++ b/app/models/news.rb @@ -2,21 +2,18 @@ class News < ActiveRecord::Base belongs_to :profile - has_attached_file :image, - :styles => { original: "4000x4000>", large: "800x800>", small: "250x250>",thumb: "100x100>" }, - :path => ":rails_root/public/system/images/news/:id/:style/:filename", - :url => "/system/images/news/:id/:style/:filename" + has_attached_file :image, + styles: {original: '4000x4000>', large: '800x800>', small: '250x250>', thumb: '100x100>'}, + path: ':rails_root/public/system/images/news/:id/:style/:filename', + url: '/system/images/news/:id/:style/:filename' # Validations - validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/ - validates :title, :presence => true - validates :content, :presence => true - validates :profile, :presence => true - + validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/ + validates :title, :content, :profile, presence: true # Scopes - scope :d_published, -> {where('d_publish <= ?',Time.zone.today)} - scope :not_removed, -> {where('d_remove > ?',Time.zone.today)} - scope :public_n, -> {where(public: true)} - scope :latest, -> {order(created_at: :asc).limit(5)} + scope :d_published, -> { where('d_publish <= ?', Time.zone.today) } + scope :not_removed, -> { where('d_remove > ?', Time.zone.today) } + scope :public_n, -> { where(public: true) } + scope :latest, -> { order(created_at: :asc).limit(5) } end diff --git a/app/models/nomination.rb b/app/models/nomination.rb index 1c609f81c..9c5bf5f48 100644 --- a/app/models/nomination.rb +++ b/app/models/nomination.rb @@ -8,6 +8,6 @@ class Nomination < ActiveRecord::Base after_create :send_email def send_email - ElectionMailer.nominate_email(self).deliver + ElectionMailer.nominate_email(self).deliver_now end end diff --git a/app/models/notice.rb b/app/models/notice.rb index e8319d6ba..06ed5b229 100644 --- a/app/models/notice.rb +++ b/app/models/notice.rb @@ -1,35 +1,27 @@ #encoding: UTF-8 class Notice < ActiveRecord::Base # Relationships - # Paperclip attachment # The storage folder require the use of Sendfile. has_attached_file :image, - :styles => {large: "400x400>",small: "250x250>"}, - :path => ":rails_root/storage/notices/:id/:style-:filename" + styles: { large: '400x400>', small: '250x250>' }, + path: ':rails_root/storage/notices/:id/:style-:filename' # Validations - validates_presence_of :title,:description,:sort - validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/ + validates :title, :description, :sort, presence: true + validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/ # Scopes - scope :d_published, -> {where('d_publish <= ?',Time.zone.today)} - scope :not_removed, -> {where('d_remove > ?',Time.zone.today)} - scope :public_n, -> {where(public: true)} + scope :d_published, -> { where('d_publish <= ?', Time.zone.today) } + scope :not_removed, -> { where('d_remove > ?', Time.zone.today) } + scope :public_n, -> { where(public: true) } + scope :published, -> { order(sort: :asc).d_published.not_removed } # Assures dates are set for queries # /d.wessman before_create :check_dates before_update :check_dates - # Methods - - # Return: all notices valued as published - # /d.wessman - def self.published - order(sort: :asc).d_published.not_removed - end - # Return: all published and public notices # /d.wessman def self.public_published @@ -40,32 +32,26 @@ def self.public_published # /d.wessman def display(bool) if bool == true - self.d_publish = Time.zone.today - 2.days - self.d_remove = "2094-03-25" - self.save - else bool == false - self.d_remove = Time.zone.today - 2.days - self.save + update(d_publish: Time.zone.today - 2.days, d_remove: '2094-03-25') + else + update(d_remove: Time.zone.today - 2.days) end end # Return: true if notice is valued to display or not def displayed? - return (self.d_publish <= Time.zone.today) && (self.d_remove > Time.zone.today) + d_publish <= Time.zone.today && d_remove > Time.zone.today end # Assures dates are set (if not present) to allow for good queries # Also my 100th birthday! # /d. wessman def check_dates - if(self.d_publish.nil?) && (self.d_remove.nil?) - self.d_remove = "2094-03-25" - self.d_publish = Time.zone.today - elsif(self.d_publish?) - self.d_remove = "2094-03-25" - elsif(self.d_remove?) + if d_publish.nil? self.d_publish = Time.zone.today end + if d_remove.nil? + self.d_remove = '2094-03-25' + end end - -end \ No newline at end of file +end diff --git a/app/models/profile.rb b/app/models/profile.rb index b6cb8e346..b21016f9e 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -1,6 +1,5 @@ # encoding: UTF-8 class Profile < ActiveRecord::Base - # Associations belongs_to :user has_and_belongs_to_many :posts @@ -9,16 +8,15 @@ class Profile < ActiveRecord::Base has_many :councils, through: :posts # Attachment - has_attached_file :avatar, - :styles => { medium: "300x300>", thumb: "100x100>" }, - :path => ":rails_root/storage/profile/:id/:style/:filename" - + has_attached_file :avatar, + styles: {medium: '300x300>', thumb: '100x100>'}, + path: ':rails_root/storage/profile/:id/:style/:filename' # Validations - validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/ + validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/ # Only on update! - validates_presence_of :name, :lastname, on: :update - validates_inclusion_of :start_year, in: 1954..(Time.zone.today.year+1), on: :update + validates :name, :lastname, presence: true, on: :update + validates :start_year, inclusion: { in: 1954..(Time.zone.today.year + 1) }, on: :update def full_name "#{name} #{lastname}".strip @@ -34,38 +32,30 @@ def car_councils # Check if profile has user data (name and lastname) # /d.wessman def has_profile_data? - return (self.name? && self.lastname?) + name.present? && lastname.present? end # Returns true if profile is fresh # /d.wessman def fresh? - return self.created_at == self.updated_at + created_at == updated_at end # Returns true if user is equal to profiles user # /d.wessman def owner?(user) - (self.user == user) + self.user == user end # Check if user has post, and in that case what first_post is set to # /d.wessman def check_posts - if(self.posts.count > 0) && (self.first_post?) - return - end - if(self.posts.count > 0) - self.first_post = self.posts.first.id - self.save - end + if posts.count > 0 && first_post == false + update(first_post: posts.first.id) + end end def print - if (self.name) && (self.lastname) - %(#{self.name} #{self.lastname}) - elsif (self.name) - self.name - end + %(#{name} #{lastname}) end end diff --git a/app/models/rent.rb b/app/models/rent.rb index 7bad90dc5..c3b587397 100644 --- a/app/models/rent.rb +++ b/app/models/rent.rb @@ -31,6 +31,7 @@ class Rent < ActiveRecord::Base # /d.wessman scope :active, -> { where(aktiv: true).where.not(status: 'Nekad') } + # To scope all rents between two dates # /d.wessman scope :between, ->(from, to) { where('? >= d_from AND ? <= d_til', to, from) } diff --git a/app/models/role.rb b/app/models/role.rb index 3f9de30f1..02b13af1b 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,5 +1,4 @@ # encoding: utf-8 - class Role < ActiveRecord::Base has_many :users end diff --git a/app/models/user.rb b/app/models/user.rb index 4f2f3c60d..7c61a756a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,15 +1,15 @@ # encoding:UTF-8 require 'net/http' -class User < ActiveRecord::Base - has_one :profile +class User < ActiveRecord::Base + has_one :profile belongs_to :role - has_many :posts, through: 'profiles' + has_many :posts, through: :profile devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable - validates_uniqueness_of :username + validates :username, uniqueness: true validate :is_f_member after_create :create_profile_for_user @@ -19,13 +19,13 @@ def create_profile_for_user end def is_f_member - errors.add :f_member, "är inte medlem i F-sektionen" unless @f_member || self.persisted? + errors.add :f_member, 'är inte medlem i F-sektionen' unless @f_member || self.persisted? end def check_f_membership(civic) url = URI.parse("http://medcheck.tlth.se/?ssid=#{civic.gsub(/[^0-9]/i, "")}") req = Net::HTTP::Get.new(url.to_s) - res = Net::HTTP.start(url.host, url.port) {|http| + res = Net::HTTP.start(url.host, url.port) { |http| http.request(req) } diff --git a/app/services/cafe_setup_week.rb b/app/services/cafe_setup_week.rb new file mode 100644 index 000000000..d6add627a --- /dev/null +++ b/app/services/cafe_setup_week.rb @@ -0,0 +1,28 @@ +#encoding: UTF-8 +class CafeSetupWeek + def initialize(day, lp) + @day = day + @lp = lp + end + + def setup(start, stop) + preview(start,stop).each do |cwork| + cwork.save + end + end + + def preview(start, stop) + @cworks = [] + (start..stop).each do |lv| + (0..4).each do + @cworks << CafeWork.new(work_day: @day, lp: @lp, pass: 1, lv: lv, d_year: @day.year) + @cworks << CafeWork.new(work_day: @day, lp: @lp, pass: 2, lv: lv, d_year: @day.year) + @cworks << CafeWork.new(work_day: @day + 2.hours, lp: @lp, pass: 3, lv: lv, d_year: @day.year) + @cworks << CafeWork.new(work_day: @day + 2.hours, lp: @lp, pass: 4, lv: lv, d_year: @day.year) + @day = @day + 1.days + end + @day = @day + 2.days + end + @cworks + end +end diff --git a/app/views/admin/cafe_works/_form.html.erb b/app/views/admin/cafe_works/_form.html.erb new file mode 100644 index 000000000..bafd35036 --- /dev/null +++ b/app/views/admin/cafe_works/_form.html.erb @@ -0,0 +1,22 @@ +<%= form_for([:admin, @cafe_work]) do |form| %> + <%= render 'shared/form_errors', current: @cafe_work %> + <%= form.label 'Datum', class: 'reg-label' %> +
+ <%= form.text_field :work_day, class: 'form-control datetimepicker' %> +
+ <%= form.label 'Pass (1 & 2, 08:00-10:00) (3 & 4, 10:00-13:00)', class: 'reg-label' %> +
+ <%= form.number_field :pass, min: 1, max: 4, class: 'form-control' %> +
+ <%= form.label 'Läsperiod', class: 'reg-label' %> +
+ <%= form.number_field :lp, min: 1, max: 4, class: 'form-control' %> +
+ <%= form.label 'Läsvecka', class: 'reg-label' %> +
+ <%= form.number_field :lv, min: 1, max: 7, class: 'form-control' %> +
+
+ <%= form.submit "Spara", class: 'btn-u pull-right' %> +
+<% end %> diff --git a/app/views/admin/cafe_works/_links.html.erb b/app/views/admin/cafe_works/_links.html.erb new file mode 100644 index 000000000..222fff9bb --- /dev/null +++ b/app/views/admin/cafe_works/_links.html.erb @@ -0,0 +1,5 @@ +
+ <%= link_to("Admin - start", admin_hilbert_path, class: "btn btn-u") %> <%= link_to("Hilbert - start", hilbert_path, class: "btn btn-u") %> + <% if @cwork.present? && !@cwork.new_record? %> <%= link_to("Jobb - vanlig vy", cafe_work_path(@cwork), class: "btn btn-u") %> + <% end %> +
\ No newline at end of file diff --git a/app/views/admin/cafe_works/_setup_form.html.erb b/app/views/admin/cafe_works/_setup_form.html.erb new file mode 100644 index 000000000..570c7cf15 --- /dev/null +++ b/app/views/admin/cafe_works/_setup_form.html.erb @@ -0,0 +1,22 @@ +<%= form_for(@cafe_work, method: :post, url: {action: 'setup_create'}) do |f| %> + <%= render 'shared/form_errors', current: @cafe_work %> +
+ <%= f.label 'Läsveckor', class: 'reg-label' %> +
+ <%= number_field_tag :lv_first, @lv_first, min: 1, max: 37, class: 'form-control', placeholder: "Från" %> + <%= number_field_tag :lv_last, @lv_last, min: 1, max: 37, class: 'form-control', placeholder: "Till" %> +
+ <%= f.label 'Läsperiod', class: 'reg-label' %> +
+ <%= f.number_field :lp, min: 1, max: 4, class: 'form-control' %> +
+ <%= f.label 'Datum första passet', class: 'reg-label' %> +
+ <%= f.text_field :work_day, class: 'form-control datetimepicker' %> +
+ +
+ <%= f.submit "Spara", class: 'btn-u pull-left' %> + <%= f.submit "Förhandsgranska", class: 'btn-u pull-right' %> +
+<% end %> diff --git a/app/views/admin/cafe_works/destroy.js.erb b/app/views/admin/cafe_works/destroy.js.erb new file mode 100644 index 000000000..bd160754a --- /dev/null +++ b/app/views/admin/cafe_works/destroy.js.erb @@ -0,0 +1,3 @@ +$('#<%=%(cafe_work_#{@id})%>').fadeOut(); +$('#<%=%(cafe_work_#{@id})%>').html(''); +$('#status').text("Jobbpasset togs bort").effect("bounce", 1500); diff --git a/app/views/admin/cafe_works/edit.html.erb b/app/views/admin/cafe_works/edit.html.erb new file mode 100644 index 000000000..bbeea0172 --- /dev/null +++ b/app/views/admin/cafe_works/edit.html.erb @@ -0,0 +1,12 @@ +
+
+
+ <%= label_tag 'Redigera cafepass', nil, class: 'reg-header' %> + <%= render 'links' %> + <%= render 'form' %> + <%= link_to 'Visa cafepass', @cwork, class: "btn btn-u" %> + <%= link_to 'Ta bort passet', @cwork, method: :delete, class: "btn btn-u" %> + <%= link_to 'Tillbaka till Hilbert', :hilbert, class: "btn btn-u" %> +
+
+
\ No newline at end of file diff --git a/app/views/admin/cafe_works/index.html.erb b/app/views/admin/cafe_works/index.html.erb new file mode 100644 index 000000000..c352b87c5 --- /dev/null +++ b/app/views/admin/cafe_works/index.html.erb @@ -0,0 +1,74 @@ +<% provide(:title, 'Hilbert Café') %> +<%= stylesheet_link_tag "fullcalendar-custom", media: "print" %> +
+
+
+

Administration för Hilbert Café

+
+ <%= grid(@cwork_grid) do |g| + g.row_attributes do |post| + if (post.has_worker?) + {style: 'background: rgba(252, 155, 0,0.7);', id: dom_id(post)} + else + {id: dom_id(post)} + end + end + g.column name: "Datum:", attribute: "work_day" + g.column name: "Läsvecka", attribute: "lv" + g.column name: "Läsperiod", attribute: "lp" + g.column name: "Pass", attribute: "pass" + g.column name: "Visa" do |post| + link_to("Visa", admin_cafe_work_path(post)) + end + g.column name: "Ta bort" do |post| + link_to("Ta bort", admin_cafe_work_path(post), remote: true, method: :delete, html: {id: dom_id(post)}) + end + end -%> + +
+
+
+

F.A.Q.

+
+ <% @faqs.each do |f| %> +
+ +
+
+ <%= simple_format(f.answer) %> + <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Redigera fråga"), edit_faq_path(f), class: "btn-u btn-u-small pull-right" %> +
+
+
+ <% end %> +
    +
  • <%= link_to("Ställ ny fråga", new_faq_path(category: "Hilbert")) %>
  • + <% if @faq_unanswered > 0 %> +
  • <%= link_to("Det finns " + pluralize(@faq_unanswered, "obesvarad FAQ"), faqs_path()) %>
  • + <% end %> +
+ + +
+
+
+

Verktyg

+
    +
  • <%= link_to("Rensa sökning", admin_hilbert_path) %>
  • +
  • <%= link_to("Skapa pass för läsperiod", admin_setup_cafe_path) %>
  • +
  • <%= link_to("Skapa enskilt pass", new_admin_cafe_work_path) %>
  • +
  • <%= link_to("Nyckelpiga", :nyckelpiga) %>
  • +
+
+
+
+
+
\ No newline at end of file diff --git a/app/views/admin/cafe_works/new.html.erb b/app/views/admin/cafe_works/new.html.erb new file mode 100644 index 000000000..2d2ffb2a4 --- /dev/null +++ b/app/views/admin/cafe_works/new.html.erb @@ -0,0 +1,9 @@ +
+
+
+ <%= label_tag 'Cafejobb',nil, :class => 'reg-header'%> + <%= render 'form'%> + <%= link_to 'Tillbaka till cafebokning', :admin_cafe_works %> +
+
+
\ No newline at end of file diff --git a/app/views/admin/cafe_works/remove_worker.js.erb b/app/views/admin/cafe_works/remove_worker.js.erb new file mode 100644 index 000000000..5d95e801e --- /dev/null +++ b/app/views/admin/cafe_works/remove_worker.js.erb @@ -0,0 +1,2 @@ +$('#jobbare').fadeOut(); +$('#status').text("Jobbare borttagen").effect('highlight'); diff --git a/app/views/admin/cafe_works/setup.html.erb b/app/views/admin/cafe_works/setup.html.erb new file mode 100644 index 000000000..b43002242 --- /dev/null +++ b/app/views/admin/cafe_works/setup.html.erb @@ -0,0 +1,40 @@ +<% provide(:title, 'Hilbert Café - Setup') %> +
+
+ <%= render 'links' %> +
+

Skapa jobbpass

+

Genom att fylla i datum och tid för läsperiodens första pass + så genereras en förhandsvisning för hela läsperioden.

+ +

För att lägga till enskilda pass går ni in på

+ <%= link_to("Enskilt pass", new_admin_cafe_work_path, class: "btn btn-u") %> + <%= render 'setup_form' %> +
+ + <% if !@cafe_works.empty? %> +
+ <% @cafe_works.group_by(&:lv).each do |week, work| %> +
+ +
+
+ <% work.each do |w| %> +
+ <%= w.print %> +
+
+ <% end %> +
+
+
+ <% end %> +
+ <% end %> +
+
+
diff --git a/app/views/admin/cafe_works/show.html.erb b/app/views/admin/cafe_works/show.html.erb new file mode 100644 index 000000000..6769d53bb --- /dev/null +++ b/app/views/admin/cafe_works/show.html.erb @@ -0,0 +1,57 @@ +<% provide(:title, 'Administratör Hilbert Café') %> +
+
+ <%= render 'links' %> +

Cafejobb - ID <%= @cafe_work.id %> Admin

+ <%= render 'form' %> +

Jobbare

+ <% if @cafe_work.has_worker? %> + + +
+ + + + + + + + + + + + + + + + + + + <% if @cafe_work.access_code.present? %> + + + + + <% end %> + +
+ <% if @cafe_work.profile.present? %> + <%= link_to(@cafe_work.worker.p_name, profile_path(@cafe_work.profile)) %> + <% else %> + <%= @cafe_work.worker.p_name %> + <% end %> +
<%= @cafe_work.email %>
<%= @cafe_work.phone %>
Cafetävling<%= (@cafe_work.utskottskamp) ? "Ja" : "Nej" %>
Kod:<%= @cafe_work.access_code %>
+
+ <%= link_to("Ta bort jobbare", + remove_worker_admin_cafe_work_path(@cafe_work), class: "btn btn-u", + remote: true, method: :patch) %> +
+
+ + <% else %> +

Jobbare saknas

+ <%= link_to("Ta bort pass", admin_cafe_work_path(@cafe_work), + method: :delete, class: "btn btn-u") %> + <% end %> +
+
diff --git a/app/views/admin/elections/_form.html.erb b/app/views/admin/elections/_form.html.erb index d7dab24f1..8177f5ff6 100644 --- a/app/views/admin/elections/_form.html.erb +++ b/app/views/admin/elections/_form.html.erb @@ -1,55 +1,56 @@ <%= form_for([:admin, @election]) do |f| %> <%= render 'shared/form_errors', current: @election %>
-
- <%= f.label 'Titel', :class => 'reg-label' %> +
+ <%= f.label 'Titel', class: 'reg-label' %>
- <%= f.text_field :title, :class => 'form-control' %> + <%= f.text_field :title, class: 'form-control' %>
- <%= f.label 'Öppnar', :class => 'reg-label' %> + <%= f.label 'Öppnar', class: 'reg-label' %>
- <%= f.datetime_select :start, :class => 'form-control' %> + <%= f.text_field :start, class: 'form-control datetimepicker1' %>
- <%= f.label 'Stänger', :class => 'reg-label' %> + <%= f.label 'Stänger', class: 'reg-label' %>
- <%= f.datetime_select :end, :class => 'form-control' %> + <%= f.text_field :end, class: 'form-control datetimepicker2' %>
- <%= f.label 'Url', :class => 'reg-label' %>
+ <%= f.label 'Url', class: 'reg-label' %>
T.ex. ht-14 (endast a-z, 1-9 och -)
- <%= f.text_field :url, :class => 'form-control' %> + <%= f.text_field :url, class: 'form-control' %>
-
- <%= f.label 'Beskrivning av valet', :class => 'reg-label' %> +
+ <%= f.label 'Beskrivning av valet', class: 'reg-label' %>
- <%= f.text_area :description, :class => 'form-control', size: "40x2" %> + <%= f.text_area :description, class: 'form-control', size: "40x2" %>
<% if @election.new_record? == false %> <%= link_to 'Lägg till fler texter', edit_admin_election_path(@election), class: "btn btn-u" %>
<% end %> - <%= f.label 'Länk för intervjutider - styrelseposter', :class => 'reg-label' %> + <%= f.label 'Länk för intervjutider - styrelseposter', class: 'reg-label' %>
- <%= f.text_field :mail_styrelse_link, :class => 'form-control', size: "40x2" %> + <%= f.text_field :mail_styrelse_link, class: 'form-control', size: "40x2" %>
- <%= f.label 'Länk för intervjutider - övriga', :class => 'reg-label' %>
+ <%= f.label 'Länk för intervjutider - övriga', class: 'reg-label' %>
Om ingen fylls i för styrelseposter så används denna.
- <%= f.text_field :mail_link, :class => 'form-control', size: "40x2" %> + <%= f.text_field :mail_link, class: 'form-control', size: "40x2" %>
- <%= f.label 'Synlig?', :class => 'reg-label' %> - <%= f.check_box :visible, :class => 'form-control' %> + <%= f.label 'Synlig?', class: 'reg-label' %> + <%= f.check_box :visible, class: 'form-control' %>
<% if @posts %>
- <%= label_tag 'Poster att söka', nil, :class => 'reg-header' %> + <%= label_tag 'Poster att söka', nil, class: 'reg-header' %>
<% @posts.in_groups_of(10, false) do |row_posts| %>
<% row_posts.each do |post| %>
- <%= f.check_box(:post_ids, {multiple: true}, post.id, nil) %><%= f.label :post_ids, post.title, :value => false, :class => 'reg-label' %> + <%= f.check_box(:post_ids, {multiple: true}, post.id, nil) %> + <%= f.label :post_ids, post.title, value: false, class: 'reg-label' %>
<% end %>
@@ -58,6 +59,6 @@
<% end %>
- <%= f.submit "Spara", :class => 'btn-u' %> + <%= f.submit "Spara", class: 'btn-u' %>
-<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/admin/elections/index.html.erb b/app/views/admin/elections/index.html.erb index c57a1cc56..5db33e79d 100644 --- a/app/views/admin/elections/index.html.erb +++ b/app/views/admin/elections/index.html.erb @@ -4,4 +4,5 @@
  • <%=link_to(elec.title,admin_election_path(elec))%>
  • <%end%> -
    \ No newline at end of file + <%=link_to('Nytt val',new_admin_election_path)%> +
    diff --git a/app/views/admin/elections/new.html.erb b/app/views/admin/elections/new.html.erb index 1e8289ac7..380fb1f00 100644 --- a/app/views/admin/elections/new.html.erb +++ b/app/views/admin/elections/new.html.erb @@ -1,10 +1,10 @@
    - <%= label_tag 'Nytt val',nil, :class => 'reg-header'%> + <%= label_tag 'Nytt val',nil, class: 'reg-header'%> <%= render 'form'%> <%= link_to 'Visa val',elections_path %>
    <%= link_to 'Tillbaka till startsida', root_url %>
    -
    \ No newline at end of file +
    diff --git a/app/views/admin/elections/show.html.erb b/app/views/admin/elections/show.html.erb index 8b1e6bc01..9e16280f6 100644 --- a/app/views/admin/elections/show.html.erb +++ b/app/views/admin/elections/show.html.erb @@ -1,9 +1,9 @@ <% provide(:title, 'Val') %>
    - <%= label_tag 'Inställningar', nil, :class => 'reg-header' %> + <%= label_tag 'Inställningar', nil, class: 'reg-header' %> <%= render 'form' %>
    - <% if (current_user) && current_user.admin? %> + <% if can? :manage,:all %> <%= link_to 'Radera val', admin_election_path(@election), class: 'btn btn-u',data: {confirm: 'Valet raderas och kan inte återställas, är du säker?'}, method: :delete %> <% end %> diff --git a/app/views/admin/rents/_form.html.erb b/app/views/admin/rents/_form.html.erb index d5ed7d481..5cb4e4f26 100644 --- a/app/views/admin/rents/_form.html.erb +++ b/app/views/admin/rents/_form.html.erb @@ -9,7 +9,7 @@ <%= f.label 'Disclaimer', class: 'reg-label' %> <%= f.check_box :disclaimer, id: "accepted_disclaimer" %> <%= f.label 'Service', class: 'reg-label' %> - <%= f.check_box :service %> + <%= f.check_box :services %>
    <%= f.label 'Namn & Efternamn', class: 'reg-label' %> diff --git a/app/views/cafe_mailer/sign_up_email.html.erb b/app/views/cafe_mailer/sign_up_email.html.erb new file mode 100644 index 000000000..e6d9f335c --- /dev/null +++ b/app/views/cafe_mailer/sign_up_email.html.erb @@ -0,0 +1,49 @@ + + + + + + + <%if attachments.inline['hilbert.jpg']%> + <%= image_tag attachments['hilbert.jpg'].url %> + <%end%> +

    Hej <%=@cafe_work.name %>

    +

    Du har skrivit upp dig för att arbeta i Hilbert Café med följande uppgifter (ID: <%=@cafe_work.id%>).

    + + + + + + + + + + + + + + + + + + + + + + + <%if @cafe_work.access_code.present?%> + + + + + <%end%> + +
    Namn:<%=%(#{@cafe_work.name} #{@cafe_work.lastname})%>
    Epost:<%=@cafe_work.email%>
    Telefon:<%=@cafe_work.phone%>
    Datum:<%=@cafe_work.print_date%>
    Länk:<%=link_to(@cafe_work.p_url,@cafe_work.p_url)%>
    Kod:<%= @cafe_work.access_code%>
    +
    +

    För att redigera dina uppgifter eller hoppa av så följer du länken.

    +

    Har du några frågor så svarar du enklast direkt på detta mejl.

    + +

    Mvh,
    + Cafemästarna

    + + \ No newline at end of file diff --git a/app/views/cafe_mailer/sign_up_email.text.erb b/app/views/cafe_mailer/sign_up_email.text.erb new file mode 100644 index 000000000..fa7c91558 --- /dev/null +++ b/app/views/cafe_mailer/sign_up_email.text.erb @@ -0,0 +1,21 @@ +Hej <%=@cafe_work.name.to_s %> + +=============================================== + +Du har skrivit upp dig för att arbeta i Hilbert Café med följande uppgifter (ID: <%=@cafe_work.id%>). + +Namn: <%=@cafe_work.name.to_s%> <%=@cafe_work.lastname.to_s%> +Epost: <%=@cafe_work.email.to_s%> +Telefon: <%=@cafe_work.phone.to_s%> +Datum: <%=@cafe_work.print_date%> +Länk: <%=@cafe_work.p_url%> +<%if !@cafe_work.access_code.nil?%> +Kod: <%=@cafe_work.access_code%> +<%end%> + +För att redigera dina uppgifter eller hoppa av så följer du länken. +Har du några frågor så svarar du enklast direkt på detta mejl. + + +Mvh, +Cafemästarna \ No newline at end of file diff --git a/app/views/cafe_works/_authorization.html.erb b/app/views/cafe_works/_authorization.html.erb new file mode 100644 index 000000000..cdbdd9409 --- /dev/null +++ b/app/views/cafe_works/_authorization.html.erb @@ -0,0 +1,10 @@ +<%=form_for(@cwork, url: authorize_cafe_work_url(@cwork), remote: true ) do |f|%> + <%= f.label 'Kod', :class => 'reg-label'%> + +
    + <%= f.text_field :access_code, value: nil, class: 'form-control'%> +
    +
    + <%= f.submit "Auktorisera",class: 'btn-u pull-right' %> +
    +<%end%> \ No newline at end of file diff --git a/app/views/cafe_works/_form.html.erb b/app/views/cafe_works/_form.html.erb new file mode 100644 index 000000000..bde5780fa --- /dev/null +++ b/app/views/cafe_works/_form.html.erb @@ -0,0 +1,74 @@ +<%= form_for(@cafe_work, url: {action: :update_worker}) do |f| %> + <%= render 'shared/form_errors', current: @cafe_work %> +
    + <%= f.label 'Namn & Efternamn', class: 'reg-label' %> +
    +
    <%= f.text_field :name, class: 'form-control', placeholder: "Förnamn" %>
    +
    <%= f.text_field :lastname, class: 'form-control', placeholder: "Efternamn" %>
    +
    +
    + <%= f.label 'E-post & telefon', class: 'reg-label' %> +
    +
    +
    <%= f.email_field :email, class: 'form-control', placeholder: "E-post" %>
    +
    <%= f.phone_field :phone, class: 'form-control', placeholder: "Telefon" %>
    +
    +
    + <% if @cafe_work.access_code.present? %> + <%= f.label 'Kod', class: 'reg-label' %> +

    Koden måste fyllas i för att ändringar ska sparas

    +
    + <%= f.text_field :access_code, class: 'form-control', placeholder: "Kod", value: nil %> +
    + <% end %> + <% if @councils %> +

    Utskottskampen

    +
    +
    + <%= f.label :utskottskamp, "Delta i cafétävlingen?", value: false, class: 'reg-label' %> +

    Ditt namn kommer synas i resultatet

    + <%= f.check_box :utskottskamp, class: 'form-control', value: @cafe_work.utskottskamp %> +
    + <%= f.label "Välj ett eller flera utskott att representera", class: 'reg-label' %> +
    + <%= f.collection_check_boxes(:council_ids, @councils, :id, :title, class: "form-control") do |b| %> + + <%= b.check_box %> + <%= b.label %>
    +
    + <% end %> +
    +
    +
    + <% end %> + <% if @cafe_work.editable? %> + <% if !@cafe_work.has_worker? %> +
    +

    Genom att trycka på spara accepterar du att dina personuppgifter hanteras elektroniskt. + Dina uppgifter kan endast ses av administratörer, cafeansvariga samt nyckelpigor.

    +
    + <% end %> +
    + <%= f.submit "Spara", class: 'btn-u pull-right' %> +
    + <% else %> +

    Det går inte längre att skriva upp sig på passet eller redigera.

    + <% end %> +<% end %> +<% if @cafe_work.has_worker? %> + <% if @authenticated %> + <%= form_for(@cafe_work, url: remove_worker_cafe_work_path(@cafe_work)) do |f| %> + <%= f.label 'Hoppa av', class: 'reg-label', id: 'leave_status' %> +

    Din kod måste fyllas i för att kunna hoppa av passet

    +
    + <%= f.text_field :access_code, class: 'form-control', placeholder: "Kod", value: nil %> +
    + <%= f.submit("Hoppa av", class: "btn btn-u") %>
    + <% end %> + <% else %> + <%= link_to("Hoppa av", remove_worker_cafe_work_path(@cafe_work), class: "btn btn-u", method: :patch) %> +
    + <% end %> + +<% end %> + diff --git a/app/views/cafe_works/authorize.js.erb b/app/views/cafe_works/authorize.js.erb new file mode 100644 index 000000000..a97783d04 --- /dev/null +++ b/app/views/cafe_works/authorize.js.erb @@ -0,0 +1,7 @@ +<% if @authenticated%> + $('#authorization').hide(); + $('#after_authorization').append("<%= escape_javascript( render partial: 'form')%>").show(); + $('#status').text("Korrekt kod, du kan nu redigera passet.").effect("bounce",3000); +<%else%> + $('#status').text("Felaktig kod").effect("bounce",3000); +<%end%> \ No newline at end of file diff --git a/app/views/cafe_works/index.html.erb b/app/views/cafe_works/index.html.erb new file mode 100644 index 000000000..c8889e1e8 --- /dev/null +++ b/app/views/cafe_works/index.html.erb @@ -0,0 +1,58 @@ +<% provide(:title, 'Hilbert Café') %> +<%= stylesheet_link_tag "fullcalendar-custom", media: "print" %> +
    +
    +
    +

    Välkommen till Hilbert Café - Läsvecka <%= @lv %> (BETA)

    + Stöter ni på problem eller om det blir fel, hör gärna av er + till <%= link_to('Cafemästare','http://fsektionen.se/kontakt/8') %> + eller <%= render partial: 'contacts/kontakt', locals: {name: 'Spindelmän'} %>. +
    +
    +
    +
    +
    +

    F.A.Q.

    +
    + <% @faqs.each do |f| %> +
    + +
    +
    + <%= simple_format(f.answer) %> +
    +
    +
    + <% end %> +
      +
    • <%= link_to("Ställ ny fråga", new_faq_path(category: "Hilbert")) %>
    • +
    +
    +
    + <% if user_signed_in? %> +
    + <% if can? :manage, CafeWork %> +

    Verktyg

    +
      +
    • <%= link_to("Gå till administrationssida", :admin_hilbert) %>
    • +
    + <% end %> + <% if can? :nyckelpiga, CafeWork %> +
      +
    • <%= link_to("Nyckelpiga", :nyckelpiga) %>
    • +
    + <% end %> +
    + <% end %> +
    +
    +
    +
    diff --git a/app/views/cafe_works/nyckelpiga.html.erb b/app/views/cafe_works/nyckelpiga.html.erb new file mode 100644 index 000000000..ff44c4222 --- /dev/null +++ b/app/views/cafe_works/nyckelpiga.html.erb @@ -0,0 +1,39 @@ +<% provide(:title, 'Hilbert Café') %> +
    +
    +

    <%= label_tag 'Cafebokning - nyckelpiga', nil, class: 'reg-header' %>

    +
    +
    + <%= form_tag(nyckelpiga_path, {method: 'get'}) do |f| %> + <%= text_field_tag(:date, @date.iso8601, class: "form-control datetimepicker") %> + <%= submit_tag "Visa", class: "btn btn-u" %> + <% end %> +
    +
    + <% if @works %> + + + + + + + + + + + + <% @works.each do |work| %> + + + + + + + + <% end %> + +
    IDPassFörnamnEfternamnTelefon
    <%= link_to(work.id, work) %><%= work.pass %><%= (work.profile.present?) ? link_to(work.name, work.profile) : work.name %><%= work.lastname %><%= work.phone %>
    + <% end %> +
    + <%= link_to("Startsida för Hilbert", :hilbert, class: "btn btn-u") %> +
    diff --git a/app/views/cafe_works/show.html.erb b/app/views/cafe_works/show.html.erb new file mode 100644 index 000000000..3a835603d --- /dev/null +++ b/app/views/cafe_works/show.html.erb @@ -0,0 +1,51 @@ +<% provide(:title, 'Hilbert Café') %> +
    +

    Cafejobb

    +
    +
    +
    + <%= fa_icon('calendar') %> + <%= @cafe_work.work_day.day %> + <%= @cafe_work.work_day.strftime('%m, %Y') %> +
    +
    +
    +
    + <%= fa_icon('clock-o') %> + <%= @cafe_work.t_start %> + till + <%= @cafe_work.t_end %> +
    +
    +
    +
    + LV <%= @cafe_work.lv %> + LP <%= @cafe_work.lp %> +
    +
    +
    +
    +

    Jobbare

    + <%= render 'shared/form_errors', current: @cafe_work %> +

    <%= @cafe_work.status_text(current_user) %>

    + <% case @cafe_work.status_view(current_user) + when :sign_up, :edit %> +
    + <%= render 'form' %> +
    + <% when :authorize %> +
    + <%= render 'authorization' %> +
    +
    +
    + <% end %> +
    + +
    + <% if can? :manage, CafeWork %> + <%= link_to("Administrera passet", admin_cafe_work_path(@cafe_work), class: "btn btn-u") %> + <% end %> + <%= link_to("Startsida för Hilbert", :hilbert, class: "btn btn-u") %> +
    +
    diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb index 60a6cfe8c..06ec92cb8 100644 --- a/app/views/events/show.html.erb +++ b/app/views/events/show.html.erb @@ -1,65 +1,74 @@ -
    -
    - <%if @event.image? %> -
    - <%else%> -
    - <%end%> -

    <%= @event.title%>

    - <%= simple_format(@event.description)%> -
    -
    -
      -
    • <%=fa_icon('calendar')%>Startar:
    • -
    • <%=fa_icon('calendar')%>Slutar:
    • - -
    -
    -
    -
      -
    • <%=@event.starts_at%>
    • -
    • <%=@event.ends_at%>
    • -
    -
    -
    -
    -
    -
      - <%if @author%>
    • <%=fa_icon('user')%>Upplagt av:
    • <%end%> -
    • <%=fa_icon('group')%>Utskott:
    • -
    -
    -
    -
      - <%if @author%>
    • <%= link_to @author.print,@author %>
    • <%end%> -
    • <%=@event.category%>
    • -
    -
    -
    -
    -
    - <% if current_user.has_role?(:event, :edit) %> - <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Redigera"), edit_event_path(@event), class: "btn-u btn-u-small" %> - <%= link_to (content_tag(:i, nil, class: "fa fa-trash-o") + " Förinta"), @event, method: :delete, data: {confirm: "Är du säker?"}, class: "btn-u btn-u-small" %> - <% end %> -
    +
    +
    + <% if @event.image? %> +
    + <% else %> +
    + <% end %> +

    <%= @event.title %>

    + <%= simple_format(@event.description) %> +
    +
    +
      +
    • <%= fa_icon('calendar') %>Startar:
    • +
    • <%= fa_icon('calendar') %>Slutar:
    • + +
    +
    +
    +
      +
    • <%= @event.starts_at %>
    • +
    • <%= @event.ends_at %>
    • +
    +
    +
    +
    +
    +
      + <% if @author %> +
    • <%= fa_icon('user') %>Upplagt av:
    • + <% end %> +
    • <%= fa_icon('group') %>Utskott:
    • +
    +
    +
    +
      + <% if @author %> +
    • <%= link_to @author.print, @author %>
    • + <% end %> +
    • <%= @event.category %>
    • +
    +
    +
    +
    +
    + <% if can? :manage, Event %> + <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Redigera"), + edit_event_path(@event), + class: "btn-u btn-u-small" %> + <%= link_to (content_tag(:i, nil, class: "fa fa-trash-o") + " Förinta"), + @event, method: :delete, + data: {confirm: "Är du säker?"}, class: "btn-u btn-u-small" %> + <% end %> +
    +
    +
    + + + + <% if @event.image? %> + +
    +
    - - - - <%if @event.image_file_name %> - -
    - -
    - - <%end%> + + <% end %>
    -
    \ No newline at end of file +
    +
    diff --git a/app/views/faqs/_form.html.erb b/app/views/faqs/_form.html.erb index 5ec7b76bc..34a449781 100644 --- a/app/views/faqs/_form.html.erb +++ b/app/views/faqs/_form.html.erb @@ -1,33 +1,23 @@ -<%= form_for(@faq, :html => { :autocomplete => 'off' }) do |f| %> - <% if @faq.errors.any? %> -
    -

    <%= pluralize(@faq.errors.count, "fel") %> gör att frågan inte kan sparas:

    - -
      - <% @faq.errors.full_messages.each do |msg| %> -
    • <%= msg.sub! "Question", "Fråga" %>
    • - <% end %> -
    -
    - <% end %> - <%= f.label 'Fråga', :class => 'reg-label'%> +<%= form_for(@faq) do |f| %> + <%= render 'shared/form_errors', current: @faq %> + <%= f.label 'Fråga', class: 'reg-label' %>
    - <%= f.text_field :question, :class => 'form-control',:placeholder => 'Fråga'%> + <%= f.text_field :question, class: 'form-control', placeholder: 'Fråga' %>
    - <%= f.label 'Kategori', :class => 'reg-label'%> + <%= f.label 'Kategori', class: 'reg-label' %>
    - <%= f.select(:category,[[],['FAQ','main'],['Bil','Bil'],['Hilbert','Hilbert']], class: 'form-control')%> + <%= f.select(:category, [[], ['FAQ', 'main'], ['Bil', 'Bil'], ['Hilbert', 'Hilbert']], class: 'form-control') %>
    - <%if @editor%> - <%= f.label 'Svar', :class => 'reg-label'%> + <% if @editor %> + <%= f.label 'Svar', class: 'reg-label' %>
    - <%= f.text_area :answer, :class => 'form-control',:placeholder => 'Svar' %> + <%= f.text_area :answer, class: 'form-control', placeholder: 'Svar' %>
    - <%end%> + <% end %>
    - <%= f.submit "Skicka",:class => 'btn-u pull-right' %> - <%if !@faq.new_record?%> - <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Ta bort fråga"), :faq, method: :delete, class: "btn-u btn-u-small"%> - <%end%> + <%= f.submit "Skicka", class: 'btn-u pull-right' %> + <% if !@faq.new_record? %> + <%= link_to(%(#{fa_icon('edit')} Ta bort fråga), faq_path(@faq), method: :delete, class: "btn-u btn-u-small") %> + <% end %>
    -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/faqs/index.html.erb b/app/views/faqs/index.html.erb index 08ceb4145..ae439a2f8 100644 --- a/app/views/faqs/index.html.erb +++ b/app/views/faqs/index.html.erb @@ -1,61 +1,67 @@ -
    -
    -
    - <%if (@editor) && (@faq_unanswered.count > 0)%> -

    Obesvarade frågor

    -
    - <%@faq_unanswered.each do |f|%> -
    - -
    -
    - <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Svara på fråga"), edit_faq_path(f), class: "btn-u btn-u-small"%> - <%= link_to (content_tag(:i, nil, class: "fa fa-trash-o") + " Ta bort fråga"), f, method: :delete, class: "btn-u btn-u-small"%> -
    -
    -
    - <%end%> -
    - <%end%> +
    +
    +
    + <% if (@editor) && (@faq_unanswered.count > 0) %> +

    Obesvarade frågor

    +
    + <% @faq_unanswered.each do |f| %> +
    + +
    +
    + <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Svara på fråga"), edit_faq_path(f), class: "btn-u btn-u-small" %> + <%= link_to (content_tag(:i, nil, class: "fa fa-trash-o") + " Ta bort fråga"), f, method: :delete, class: "btn-u btn-u-small" %> +
    +
    +
    + <% end %> +
    + <% end %> - -

    FAQ

    -
    - <%@first=true%> - <%@faq.each do |f|%> -
    - -
    -
    - <%=f.answer%> - <%if @editor%> - <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Redigera fråga"), edit_faq_path(f), class: "btn-u btn-u-small pull-right"%> - <%end%> -
    -
    -
    - <%end%> -
    -
    + +

    FAQ

    +
    + <% @first=true %> + <% @faq.each do |f| %> +
    + +
    +
    + <%= f.answer %> + <% if @editor %> + <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Redigera fråga"), edit_faq_path(f), class: "btn-u btn-u-small pull-right" %> + <% end %> +
    +
    +
    + <% end %> +
    +
    + -
    - <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Ställ fråga"), new_faq_path, class: "btn-u btn-u-small"%>
    -
    -
    +
    + <%= link_to (content_tag(:i, nil, class: "fa fa-edit") + " Ställ fråga"), new_faq_path, class: "btn-u btn-u-small" %> +
    +
    +
    +
    diff --git a/app/views/layouts/_bottombar.html.erb b/app/views/layouts/_bottombar.html.erb index 006ce66ad..2bef1039e 100644 --- a/app/views/layouts/_bottombar.html.erb +++ b/app/views/layouts/_bottombar.html.erb @@ -1,6 +1,6 @@
    diff --git a/app/views/layouts/_menu.html.erb b/app/views/layouts/_menu.html.erb index 0d605d452..3db4ad5a8 100644 --- a/app/views/layouts/_menu.html.erb +++ b/app/views/layouts/_menu.html.erb @@ -1,76 +1,66 @@ <% menus_by_location = Menu.index.group_by &:location %> - diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d925a5820..63039c4fc 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,9 +1,12 @@ - - - + + + + - <%=full_title(yield(:title))%> + <%= full_title(yield(:title)) %> @@ -11,136 +14,119 @@ - <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> + <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %> <%= favicon_link_tag 'favicon.ico' %> - <% if current_user # This script is needed for the old gallery hack. /Erik Henriksson %> - <%= javascript_tag do %> - gallery_username = '<%= j current_user.username %>'; - gallery_secret = '<%= j current_user.encrypted_password %>'; - <% end %> + <% if current_user # This script is needed for the old gallery hack. /Erik Henriksson %> + <%= javascript_tag do %> + gallery_username = '<%= j current_user.username %>'; + gallery_secret = '<%= j current_user.encrypted_password %>'; + <% end %> <% end %> - - - - -
    -
    - <%= render "layouts/topbar" %> -
    + +
    +
    + <%= render 'layouts/topbar' %>
    - +
    + - -
    - +
    + + - - + + + + + + + + + + diff --git a/app/views/posts/_form.html.erb b/app/views/posts/_form.html.erb index e7e985c5d..24d0f2c87 100644 --- a/app/views/posts/_form.html.erb +++ b/app/views/posts/_form.html.erb @@ -1,45 +1,49 @@ -<%= form_for(council_post_path(@council,@post), method: :patch) do |f| %> - <%= render 'shared/form_errors', current: @post%> -
    - <%= f.label 'Titel', :class => 'reg-label'%> -
    - <%= f.text_field :title,:class => 'form-control' %> -
    - <%= f.label 'Styrelsepost', :class => 'reg-label'%> -
    - <%= f.check_box :styrelse, checked: @post.styrelse %> -
    - <%= f.label 'Får boka bilen för utskottet', :class => 'reg-label'%> -
    - <%= f.check_box :car_rent, checked: @post.car_rent %> -
    - <%= f.label 'Väljs av?, väljs när?', class:'reg-label'%> -
    - <%= f.select :elected_by, options_for_select(["","Terminsmötet","Styrelsen","Studierådet"],@post.elected_by),class: "form-control"%> <%= f.select :elected_at, options_for_select(["","HT", "VT"],@post.elected_at),class: "form-control"%> -
    - <%= f.label 'Ansvarigt utskott', :class => 'reg-label'%> -
    - <%= f.select :council_id, - options_from_collection_for_select(@councils,:id,:title,@post.council_id), - include_blank: true, - :class => "form-control listBox"%> -
    -
    -
    - <%= f.label 'Hur många kan ha posten?', :class => 'reg-label'%> -

    0 - 0 ger * (det gör även 7 - 0)

    -

    5 - 5 get 5 (x)

    -

    4 - 5 ger 4-5

    -
    - <%= f.select :recLimit, 0..10,selected: @post.recLimit,class:'form-control' %> - <%= f.select :limit, 0..10,selected: @post.limit,class:'form-control' %> -
    -
    -
    - <%= f.label 'Beskrivning:', :class => 'reg-label'%> -
    - <%= f.text_area :description,size: '80x18',class:'form-control' %> -
    -
    +<%= form_for([@council, @post]) do |f| %> + <%= render 'shared/form_errors', current: @post %> +
    + <%= f.label 'Titel', class: 'reg-label' %> +
    + <%= f.text_field :title, class: 'form-control' %> +
    + <%= f.label 'Styrelsepost', class: 'reg-label' %> +
    + <%= f.check_box :styrelse, checked: @post.styrelse %> +
    + <%= f.label 'Får boka bilen för utskottet', class: 'reg-label' %> +
    + <%= f.check_box :car_rent, checked: @post.car_rent %> +
    + <%= f.label 'Väljs av?, väljs när?', class: 'reg-label' %> +
    + <%= f.select :elected_by, options_for_select(["", "Terminsmötet", "Styrelsen", "Studierådet"], @post.elected_by), class: "form-control" %> <%= f.select :elected_at, options_for_select(["", "HT", "VT"], @post.elected_at), class: "form-control" %> +
    + <%= f.label 'Ansvarigt utskott', class: 'reg-label' %> +
    + <%= f.select :council_id, + options_from_collection_for_select(@councils, :id, :title, @post.council_id), + include_blank: true, + class: "form-control listBox" %> +
    +
    +
    + <%= f.label 'Hur många kan ha posten?', class: 'reg-label' %> +

    0 - 0 ger * (det gör även 7 - 0)

    + +

    5 - 5 get 5 (x)

    + +

    4 - 5 ger 4-5

    + +
    + <%= f.select :recLimit, 0..10, selected: @post.recLimit, class: 'form-control' %> - + <%= f.select :limit, 0..10, selected: @post.limit, class: 'form-control' %> +
    +
    +
    + <%= f.label 'Beskrivning:', class: 'reg-label' %> +
    + <%= f.text_area :description, size: '80x18', class: 'form-control' %> +
    +
    Permissions @@ -49,15 +53,17 @@ <% @permissions.each do |permission| %> - - - - - + + + + + <% end %>
    <%= check_box_tag 'main', 0, false %>
    <%= permission.subject_class %><%= permission.action %><%= check_box_tag 'permissions[]', permission.id, @post_permissions.include?(permission.id), {array: true, class: "check_box"}%>
    <%= permission.subject_class %><%= permission.action %><%= check_box_tag 'permissions[]', permission.id, + @post_permissions.include?(permission.id), + {array: true, class: "check_box"} %>
    -
    - <%= f.submit "Spara",:class => 'btn-u pull-right' %> -
    +
    + <%= f.submit "Spara", class: 'btn-u pull-right' %> +
    <% end %> diff --git a/app/views/rent_mailer/_attributes_html.html.erb b/app/views/rent_mailer/_attributes_html.html.erb index b33aa6bdb..bdb5b50d0 100644 --- a/app/views/rent_mailer/_attributes_html.html.erb +++ b/app/views/rent_mailer/_attributes_html.html.erb @@ -26,7 +26,7 @@ <% if rent.council.present? %> Utskott: - <%= link_to(rent.council.title, council_path(rent.council)) %> + <%= link_to(rent.council.title, rent.council.p_url) %> <% end %> diff --git a/app/views/rent_mailer/active_email.html.erb b/app/views/rent_mailer/active_email.html.erb index 00f5ccf57..50bf6cb47 100644 --- a/app/views/rent_mailer/active_email.html.erb +++ b/app/views/rent_mailer/active_email.html.erb @@ -14,50 +14,7 @@ <% end %>
    -

    Bokningens uppgifter (ID: <%= @rent.id %>).

    - - - - - - - - - - - - - - - - - - - <% if @rent.purpose.present? %> - - - - - <% end %> - <% @council = Council.find_by_id(@rent.council_id) %> - <% if @council %> - - - - - <% end %> - - - - - <% if @rent.access_code.present? %> - - - - - <% end %> - -
    Namn:<%= @rent.p_name %>
    Epost:<%= @rent.email %>
    Telefon:<%= @rent.phone %>
    Datum:<%= @rent.p_time %>
    Syfte:<%= simple_format(@rent.purpose) %>
    Utskott:<%= link_to(@council.title, council_path(@council)) %>
    Länk:<%= link_to('Bokning', @rent.p_url) %>
    Kod:<%= @rent.access_code %>
    +<%= render 'attributes_html', rent: @rent%>

    Mvh,
    diff --git a/app/views/rent_mailer/rent_email.html.erb b/app/views/rent_mailer/rent_email.html.erb index a20a0fe12..e78504d22 100644 --- a/app/views/rent_mailer/rent_email.html.erb +++ b/app/views/rent_mailer/rent_email.html.erb @@ -6,49 +6,7 @@

    Hej <%= @rent.p_name %>

    -

    Du har bokat F-sektionens bil med nedanstående uppgifter (ID: <%= @rent.id %>) .

    - - - - - - - - - - - - - - - - - - - <% if @rent.purpose.blank? == false %> - - - - - <% end %> - <% if @rent.council.present? %> - - - - - <% end %> - - - - - <% if @rent.access_code.present? %> - - - - - <% end %> - -
    Namn:<%= @rent.p_name %>
    Epost:<%= @rent.email %>
    Telefon:<%= @rent.phone %>
    Datum:<%= @rent.p_time %>
    Syfte:<%= simple_format(@rent.purpose) %>
    Utskott:<%= link_to(@rent.council.title, council_path(@rent.council)) %>
    Länk:<%= link_to(@rent.p_url, @rent.p_url) %>
    Kod:<%= @rent.access_code %>
    +<%= render 'attributes_html', rent: @rent%>
    <% if (@rent.status != "Bekräftad") %> diff --git a/bin/haml b/bin/haml deleted file mode 100755 index 69847459d..000000000 --- a/bin/haml +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env ruby -# -# This file was generated by Bundler. -# -# The application 'haml' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'pathname' -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', - Pathname.new(__FILE__).realpath) - -require 'rubygems' -require 'bundler/setup' - -load Gem.bin_path('haml', 'haml') diff --git a/config/application.rb b/config/application.rb index 7e9497126..42d016ba4 100644 --- a/config/application.rb +++ b/config/application.rb @@ -18,16 +18,16 @@ class Application < Rails::Application # config.time_zone = 'Central Time (US & Canada)' # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de + config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + config.i18n.default_locale = :sv config.autoload_paths += Dir["#{config.root}/lib/**/"] + config.autoload_paths += Dir["#{config.root}/services/**/"] config.time_zone ='Stockholm' config.secret_token='53925521d781eeebea75a93a98a86e8aee9a3fac8b2be4c9ee4fed6f745899921e0b22502ee937fcfaa8cf4b471dd02ba8627ebb8b48f99c1975761c45ccd790' - config.i18n.default_locale = :sv config.assets.precompile += ['application-print.css'] - config.filter_parameters += [:password,:password_confirmation,:civic] + config.filter_parameters += [:password, :password_confirmation, :civic] config.active_record.raise_in_transactional_callbacks = true end end diff --git a/config/environments/production.rb b/config/environments/production.rb index 842053e61..03c3420eb 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -74,7 +74,7 @@ # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify - config.action_mailer.default_url_options = { :host => 'fsektionen.se' } + config.action_mailer.default_url_options = { host: 'fsektionen.se' } config.action_mailer.delivery_method = :smtp config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = false diff --git a/config/environments/test.rb b/config/environments/test.rb index cd57c79d0..0abf6bce1 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -14,7 +14,9 @@ config.eager_load = false # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_files = true + + config.serve_static_files = true + config.static_cache_control = "public, max-age=3600" # Show full error reports and disable caching. diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index ab813f264..00d163182 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,3 +1,13 @@ +Rails.application.config.assets.precompile << Proc.new do |path| + if path =~ /\.(css|js|scss|sass)\z/ + full_path = Rails.application.assets.resolve(path).to_path + app_assets_path = Rails.root.join('app', 'assets').to_path + full_path.starts_with? app_assets_path + else + false + end +end + # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. diff --git a/config/locales/en.yml b/config/locales/en.yml index b9fc6589b..d0262455c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -19,6 +19,10 @@ # To learn more, please read the Rails Internationalization guide # available at http://guides.rubyonrails.org/i18n.html. en: + time: + formats: + day: "%A %d/%m" + Hello: Hello success_create: was successfully created success_update: was successfully updated @@ -27,4 +31,3 @@ en: profile_add_information: You have to fill out your name and surname. Please fill out the other information as well. error: error prevent_save: prevents the save - diff --git a/config/locales/sv.the_role.yml b/config/locales/sv.the_role.yml new file mode 100644 index 000000000..2a0ee0fb8 --- /dev/null +++ b/config/locales/sv.the_role.yml @@ -0,0 +1,17 @@ +sv: + the_role: + role_created: Roll skapades + role_updated: Roll uppdaterades + role_deleted: Roll togs bort + section_created: Sektion skapades + section_not_created: Sektion skapades inte + section_rule_created: "Sektionsregel skapad" + section_rule_not_created: "Sektionsregel ej skapad" + section_rule_on: "Sektionsregel aktiverad" + section_rule_off: "Sektionsregel inaktiverad" + state_not_changed: "Sektionsregel ej ändraded" + section_deleted: Sektion borttagen + section_not_deleted: Sektion ej borttagen + section_rule_deleted: "Sektionsregel borttagen" + section_rule_not_deleted: "Sektionsregel ej borttagen" + access_denied: "Åtkomst nekad" \ No newline at end of file diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 5bc908714..28546afbd 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -77,7 +77,7 @@ sv: section_not_deleted: Sektion ej borttagen section_rule_deleted: "Sektionsregel borttagen" section_rule_not_deleted: "Sektionsregel ej borttagen" - access_denied: "Åtkomst nekad" + access_denied: "Åtkomst nekad" admin: roles: @@ -111,4 +111,18 @@ sv: roles_import_confirm: 'Det kan ändra behörigheter i ditt system, är du säker?' errors: + format: "%{message}" + attributes: + email: + blank: "Epost måste anges" + phone: + blank: "Telefonnummer måste anges" + name: + blank: "Förnamn måste anges" + lastname: + blank: "Efternamn måste anges" + + time: + formats: + day: "%A %d/%m" invalid-url: Inte en giltig webadress diff --git a/config/routes.rb b/config/routes.rb index 9e2aa6bda..2ea047523 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,5 @@ Fsek::Application.routes.draw do - resources :constants post "githook" => "githook#index" @@ -15,10 +14,6 @@ get 'foretag/om', controller: :static_pages, action: :company_about, as: :company_about get 'foretag/vi-erbjuder', controller: :static_pages, action: :company_offer, as: :company_offer - - - - # User-related routes devise_for :users, skip: [:sessions, :registrations], controllers: {registrations: "registrations"} devise_scope :user do @@ -40,10 +35,32 @@ get 'anvandare' => 'users#index', as: :users # Scope to change urls to swedish - scope path_names: { new: 'ny', edit: 'redigera' } do + scope path_names: {new: 'ny', edit: 'redigera'} do resources :notices + + scope :hilbertcafe do + namespace :admin do + resources :cafe_works, path: :jobb, controller: :cafe_works, except: :index do + patch :remove_worker, path: :jobbare, on: :member + end + get '/setup', controller: :cafe_works, action: :setup, as: :setup_cafe + post '/setup', controller: :cafe_works, action: :setup_create, as: :setup_cafe_create + get '', controller: :cafe_works, action: :index, as: :hilbert + post '', controller: :cafe_works, action: :index + end + resources :cafe_works, path: :jobb, only: [:show] do + patch :add_worker, path: :jobba, on: :member + patch :update_worker, path: :uppdatera, on: :member + patch :remove_worker, path: :inte_jobba, on: :member + patch :authorize, path: :auktorisera, on: :member + end + get '', controller: :cafe_works, action: :index, as: :hilbert + get '/nyckelpiga', controller: :cafe_works, action: :nyckelpiga + #get '/tavling', controller: :cafe_works, action: :tavling, as: :cafe_tavling + end + # A scope to put car-associated things under /bil # /d.wessman scope :bil do @@ -63,6 +80,7 @@ post :display, path: :visa, on: :member get :image, path: :bild, on: :member end + resources :menus, path: :meny, except: :show resources :posts, path: :poster, only: :index do @@ -130,7 +148,7 @@ end post '' => 'albums#index', as: :index_albums - resources :short_links, :except => [ :show, :update, :edit ] do + resources :short_links, except: [ :show, :update, :edit ] do collection do get 'go' => 'short_links#go' get 'check' => 'short_links#check' diff --git a/db/migrate/20410822171422_fsek_structure.rb b/db/migrate/20410822171422_fsek_structure.rb index ae6c6e1ef..3d5373dfd 100644 --- a/db/migrate/20410822171422_fsek_structure.rb +++ b/db/migrate/20410822171422_fsek_structure.rb @@ -304,13 +304,13 @@ def change t.string "email" t.string "phone" t.text "purpose" - t.boolean "disclaimer" + t.boolean "disclaimer" t.string "status", default: "Ej bestämd" - t.boolean "aktiv", default: true - t.integer "council_id" + t.boolean "aktiv", default: true + t.integer "council_id" t.integer "profile_id" - t.text "comment" t.boolean "service" + t.text "comment" t.timestamps end end @@ -323,7 +323,7 @@ def change t.datetime "created_at" t.datetime "updated_at" end - end + end unless table_exists? :subcategories create_table "subcategories" do |t| t.string "text" diff --git a/db/migrate/20410822171427_create_cafe_works.rb b/db/migrate/20410822171427_create_cafe_works.rb new file mode 100644 index 000000000..8ba7284ed --- /dev/null +++ b/db/migrate/20410822171427_create_cafe_works.rb @@ -0,0 +1,19 @@ +class CreateCafeWorks < ActiveRecord::Migration + def change + create_table :cafe_works do |t| + t.datetime :work_day + t.integer :pass + t.integer :lp + t.integer :lv + t.integer :profile_id + t.string :name + t.string :lastname + t.string :phone + t.string :email + t.boolean :utskottskamp + t.string :access_code + t.integer :d_year + t.timestamps + end + end +end diff --git a/db/migrate/20410822171429_add_cafe_works_councils.rb b/db/migrate/20410822171429_add_cafe_works_councils.rb new file mode 100644 index 000000000..f7187dcd4 --- /dev/null +++ b/db/migrate/20410822171429_add_cafe_works_councils.rb @@ -0,0 +1,8 @@ +class AddCafeWorksCouncils < ActiveRecord::Migration + def change + create_table "cafe_works_councils", id: false do |t| + t.integer "cafe_work_id" + t.integer "council_id" + end + end +end diff --git a/db/migrate/20410822171441_add_access_code_to_rents.rb b/db/migrate/20410822171441_add_access_code_to_rents.rb index e2c0a72ba..20b6747f2 100644 --- a/db/migrate/20410822171441_add_access_code_to_rents.rb +++ b/db/migrate/20410822171441_add_access_code_to_rents.rb @@ -3,7 +3,7 @@ def change add_column :rents, :access_code, :string change_column :rents, :service,:boolean, default: false change_column :rents, :disclaimer,:boolean, default: false - change_column :rents, :purpose,:text, default: "" + change_column :rents, :purpose,:text add_index :rents,:d_from add_index :rents,:d_til diff --git a/db/migrate/20410822171448_create_cafe_work_councils.rb b/db/migrate/20410822171448_create_cafe_work_councils.rb new file mode 100644 index 000000000..c974dc36f --- /dev/null +++ b/db/migrate/20410822171448_create_cafe_work_councils.rb @@ -0,0 +1,9 @@ +class CreateCafeWorkCouncils < ActiveRecord::Migration + def change + create_table :cafe_work_councils do |t| + t.integer :cafe_work_id + t.integer :council_id + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 024cc44ca..74634ac4f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,62 +11,79 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20410822171447) do +ActiveRecord::Schema.define(version: 20410822171448) do + + create_table "album_categories", force: :cascade do |t| + t.string "name", limit: 255 + t.text "text", limit: 65535 + t.boolean "visible", limit: 1 + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "album_categories_albums", id: false, force: :cascade do |t| + t.integer "album_id", limit: 4 + t.integer "album_category_id", limit: 4 + end create_table "albums", force: :cascade do |t| t.string "title", limit: 255 - t.text "description" + t.text "description", limit: 65535 t.string "author", limit: 255 t.string "location", limit: 255 - t.boolean "public" + t.boolean "public", limit: 1 t.datetime "start_date" t.datetime "end_date" t.datetime "created_at" t.datetime "updated_at" t.string "category", limit: 255 - t.integer "photo_category_id" + t.integer "photo_category_id", limit: 4 end - create_table "albums_categories", id: false, force: :cascade do |t| - t.integer "album_id" - t.integer "category_id" + create_table "albums_images", id: false, force: :cascade do |t| + t.integer "album_id", limit: 4 + t.integer "image_id", limit: 4 end - add_index "albums_categories", ["album_id", "category_id"], name: "index_albums_categories_on_album_id_and_category_id", unique: true - add_index "albums_categories", ["category_id"], name: "index_albums_categories_on_category_id" + create_table "albums_subcategories", id: false, force: :cascade do |t| + t.integer "album_id", limit: 4 + t.integer "subcategory_id", limit: 4 + end - create_table "albums_images", id: false, force: :cascade do |t| - t.integer "album_id" - t.integer "image_id" + create_table "cafe_work_councils", force: :cascade do |t| + t.integer "cafe_work_id", limit: 4 + t.integer "council_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "cafe_works", force: :cascade do |t| t.datetime "work_day" - t.integer "pass" - t.integer "lp" - t.integer "lv" - t.integer "profile_id" + t.integer "pass", limit: 4 + t.integer "lp", limit: 4 + t.integer "lv", limit: 4 + t.integer "profile_id", limit: 4 t.string "name", limit: 255 t.string "lastname", limit: 255 t.string "phone", limit: 255 t.string "email", limit: 255 - t.boolean "utskottskamp" + t.boolean "utskottskamp", limit: 1 t.string "access_code", limit: 255 - t.integer "d_year" + t.integer "d_year", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "cafe_works_councils", id: false, force: :cascade do |t| - t.integer "cafe_work_id" - t.integer "council_id" + t.integer "cafe_work_id", limit: 4 + t.integer "council_id", limit: 4 end create_table "candidates", force: :cascade do |t| - t.integer "post_id" - t.integer "profile_id" - t.integer "election_id" - t.text "motivation" + t.integer "post_id", limit: 4 + t.integer "profile_id", limit: 4 + t.integer "election_id", limit: 4 + t.text "motivation", limit: 65535 t.datetime "created_at" t.datetime "updated_at" t.string "stil_id", limit: 255 @@ -76,17 +93,8 @@ t.string "lastname", limit: 255 end - add_index "candidates", ["post_id"], name: "index_candidates_on_post_id" - add_index "candidates", ["profile_id"], name: "index_candidates_on_profile_id" - - create_table "categories", force: :cascade do |t| - t.string "title", limit: 255 - t.text "description" - t.string "typ", limit: 255 - t.boolean "sub", default: false - t.datetime "created_at" - t.datetime "updated_at" - end + add_index "candidates", ["post_id"], name: "index_candidates_on_post_id", using: :btree + add_index "candidates", ["profile_id"], name: "index_candidates_on_profile_id", using: :btree create_table "constants", force: :cascade do |t| t.string "name", limit: 255 @@ -98,9 +106,9 @@ create_table "contacts", force: :cascade do |t| t.string "name", limit: 255 t.string "email", limit: 255 - t.boolean "public" - t.text "text" - t.integer "council_id" + t.boolean "public", limit: 1 + t.text "text", limit: 65535 + t.integer "council_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end @@ -108,29 +116,29 @@ create_table "councils", force: :cascade do |t| t.string "title", limit: 255 t.string "url", limit: 255 - t.text "description" - t.integer "president" - t.integer "vicepresident" + t.text "description", limit: 65535 + t.integer "president", limit: 4 + t.integer "vicepresident", limit: 4 t.string "logo_file_name", limit: 255 t.string "logo_content_type", limit: 255 - t.integer "logo_file_size" + t.integer "logo_file_size", limit: 4 t.datetime "logo_updated_at" - t.boolean "public", default: true + t.boolean "public", limit: 1, default: true t.datetime "created_at" t.datetime "updated_at" - t.integer "contact_id" + t.integer "contact_id", limit: 4 end create_table "documents", force: :cascade do |t| t.string "pdf_file_name", limit: 255 t.string "pdf_content_type", limit: 255 - t.integer "pdf_file_size" + t.integer "pdf_file_size", limit: 4 t.datetime "pdf_updated_at" t.string "title", limit: 255 - t.boolean "public" - t.boolean "download" + t.boolean "public", limit: 1 + t.boolean "download", limit: 1 t.string "category", limit: 255 - t.integer "profile_id" + t.integer "profile_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end @@ -138,129 +146,110 @@ create_table "elections", force: :cascade do |t| t.datetime "start" t.datetime "end" - t.boolean "visible" + t.boolean "visible", limit: 1 t.string "url", limit: 255 t.string "title", limit: 255 - t.text "description" + t.text "description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" - t.text "candidate_mail" - t.text "nominate_mail" - t.text "text_before" - t.text "text_during" - t.text "text_after" - t.text "extra_text" - t.text "candidate_mail_star" + t.text "candidate_mail", limit: 65535 + t.text "nominate_mail", limit: 65535 + t.text "text_before", limit: 65535 + t.text "text_during", limit: 65535 + t.text "text_after", limit: 65535 + t.text "extra_text", limit: 65535 + t.text "candidate_mail_star", limit: 65535 t.string "mail_link", limit: 255 t.string "mail_styrelse_link", limit: 255 end create_table "elections_posts", id: false, force: :cascade do |t| - t.integer "election_id" - t.integer "post_id" - end - - create_table "email_accounts", force: :cascade do |t| - t.integer "profile_id" - t.string "email", limit: 255 - t.string "title", limit: 255 - t.boolean "active" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "emails", force: :cascade do |t| - t.integer "email_account_id" - t.string "receiver", limit: 255 - t.string "subject", limit: 255 - t.text "message" - t.boolean "copy" - t.datetime "created_at" - t.datetime "updated_at" + t.integer "election_id", limit: 4 + t.integer "post_id", limit: 4 end create_table "events", force: :cascade do |t| t.string "title", limit: 255 t.string "author", limit: 255 - t.text "description" + t.text "description", limit: 65535 t.string "location", limit: 255 t.datetime "starts_at" t.datetime "ends_at" - t.boolean "all_day" + t.boolean "all_day", limit: 1 t.string "category", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.string "image_file_name", limit: 255 t.string "image_content_type", limit: 255 - t.integer "image_file_size" + t.integer "image_file_size", limit: 4 t.datetime "image_updated_at" end create_table "faqs", force: :cascade do |t| t.string "question", limit: 255 - t.text "answer" - t.integer "sorting_index" + t.text "answer", limit: 65535 + t.integer "sorting_index", limit: 4 t.datetime "created_at" t.datetime "updated_at" t.string "category", limit: 255 end - add_index "faqs", ["category"], name: "index_faqs_on_category" + add_index "faqs", ["category"], name: "index_faqs_on_category", using: :btree create_table "images", force: :cascade do |t| t.string "description", limit: 255 - t.integer "album_id" + t.integer "album_id", limit: 4 t.string "foto_file_name", limit: 255 t.string "foto_content_type", limit: 255 - t.integer "foto_file_size" + t.integer "foto_file_size", limit: 4 t.datetime "foto_updated_at" t.datetime "created_at" t.datetime "updated_at" t.datetime "captured" - t.integer "subcategory_id" + t.integer "subcategory_id", limit: 4 end create_table "lists", force: :cascade do |t| t.string "category", limit: 255 t.string "name", limit: 255 t.string "string1", limit: 255 - t.integer "int1" - t.boolean "bool1" + t.integer "int1", limit: 4 + t.boolean "bool1", limit: 1 t.datetime "created_at" t.datetime "updated_at" end create_table "menus", force: :cascade do |t| t.string "location", limit: 255 - t.integer "index" + t.integer "index", limit: 4 t.string "link", limit: 255 t.string "name", limit: 255 - t.boolean "visible" - t.boolean "turbolinks", default: true - t.boolean "blank_p" + t.boolean "visible", limit: 1 + t.boolean "turbolinks", limit: 1, default: true + t.boolean "blank_p", limit: 1 t.datetime "created_at" t.datetime "updated_at" end create_table "news", force: :cascade do |t| t.string "title", limit: 255 - t.text "content" - t.boolean "front_page" + t.text "content", limit: 65535 + t.boolean "front_page", limit: 1 t.string "image_file_name", limit: 255 t.string "image_content_type", limit: 255 - t.integer "image_file_size" + t.integer "image_file_size", limit: 4 t.datetime "image_updated_at" t.datetime "created_at" t.datetime "updated_at" - t.integer "profile_id" + t.integer "profile_id", limit: 4 end create_table "nominations", force: :cascade do |t| - t.integer "post_id" - t.integer "election_id" + t.integer "post_id", limit: 4 + t.integer "election_id", limit: 4 t.string "name", limit: 255 t.string "email", limit: 255 - t.text "motivation" + t.text "motivation", limit: 65535 t.datetime "created_at" t.datetime "updated_at" t.string "phone", limit: 255 @@ -269,33 +258,33 @@ create_table "notices", force: :cascade do |t| t.string "title", limit: 255 - t.text "description" - t.boolean "public" + t.text "description", limit: 65535 + t.boolean "public", limit: 1 t.date "d_publish" t.date "d_remove" - t.integer "sort" + t.integer "sort", limit: 4 t.string "image_file_name", limit: 255 t.string "image_content_type", limit: 255 - t.integer "image_file_size" + t.integer "image_file_size", limit: 4 t.datetime "image_updated_at" t.datetime "created_at" t.datetime "updated_at" end create_table "page_elements", force: :cascade do |t| - t.integer "displayIndex" - t.boolean "sidebar" - t.boolean "visible" - t.text "text" + t.integer "displayIndex", limit: 4 + t.boolean "sidebar", limit: 1 + t.boolean "visible", limit: 1 + t.text "text", limit: 65535 t.string "headline", limit: 255 - t.boolean "border" + t.boolean "border", limit: 1 t.string "name", limit: 255 - t.boolean "pictureR" + t.boolean "pictureR", limit: 1 t.string "picture_file_name", limit: 255 t.string "picture_content_type", limit: 255 - t.integer "picture_file_size" + t.integer "picture_file_size", limit: 4 t.datetime "picture_updated_at" - t.integer "page_id" + t.integer "page_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end @@ -303,84 +292,69 @@ create_table "pages", force: :cascade do |t| t.datetime "created_at" t.datetime "updated_at" - t.integer "council_id" + t.integer "council_id", limit: 4 end create_table "permission_posts", force: :cascade do |t| - t.integer "permission_id" - t.integer "post_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.integer "permission_id", limit: 4 + t.integer "post_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "permissions", force: :cascade do |t| - t.string "name" - t.string "subject_class" - t.string "action" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.string "subject_class", limit: 255 + t.string "action", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "photo_categories", force: :cascade do |t| t.string "name", limit: 255 t.string "text", limit: 255 - t.boolean "visible" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "phrasing_phrase_versions", force: :cascade do |t| - t.integer "phrasing_phrase_id" - t.text "value" - t.datetime "created_at" - t.datetime "updated_at" - end - - create_table "phrasing_phrases", force: :cascade do |t| - t.string "locale", limit: 255 - t.string "key", limit: 255 - t.text "value" + t.boolean "visible", limit: 1 t.datetime "created_at" t.datetime "updated_at" end create_table "posts", force: :cascade do |t| t.string "title", limit: 255 - t.integer "limit", default: 0 - t.text "description" + t.integer "limit", limit: 4, default: 0 + t.text "description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" - t.integer "council_id" - t.boolean "extra_text" + t.integer "council_id", limit: 4 + t.boolean "extra_text", limit: 1 t.string "elected_by", limit: 255 t.string "elected_at", limit: 255 - t.text "election_text" - t.boolean "styrelse" - t.integer "recLimit", default: 0 - t.boolean "car_rent" + t.text "election_text", limit: 65535 + t.boolean "styrelse", limit: 1 + t.integer "recLimit", limit: 4, default: 0 + t.boolean "car_rent", limit: 1 end create_table "posts_profiles", id: false, force: :cascade do |t| - t.integer "post_id" - t.integer "profile_id" + t.integer "post_id", limit: 4 + t.integer "profile_id", limit: 4 end create_table "profiles", force: :cascade do |t| t.string "name", limit: 255 + t.string "lastname", limit: 255 t.string "program", limit: 255 - t.integer "start_year" - t.integer "user_id" + t.integer "start_year", limit: 4 + t.integer "user_id", limit: 4 t.string "avatar_file_name", limit: 255 t.string "avatar_content_type", limit: 255 - t.integer "avatar_file_size" + t.integer "avatar_file_size", limit: 4 t.datetime "avatar_updated_at" t.datetime "created_at" t.datetime "updated_at" - t.integer "first_post" + t.integer "first_post", limit: 4 t.string "email", limit: 255 t.string "stil_id", limit: 255 t.string "phone", limit: 255 - t.string "lastname", limit: 255 end create_table "rents", force: :cascade do |t| @@ -390,37 +364,43 @@ t.string "lastname", limit: 255 t.string "email", limit: 255 t.string "phone", limit: 255 - t.text "purpose" - t.boolean "disclaimer", default: false - t.boolean "aktiv", default: true - t.integer "council_id" - t.integer "profile_id" + t.text "purpose", limit: 65535 + t.boolean "disclaimer", limit: 1, default: false + t.string "status", limit: 255, default: "Ej bestämd" + t.boolean "aktiv", limit: 1, default: true + t.integer "council_id", limit: 4 + t.integer "profile_id", limit: 4 + t.boolean "service", limit: 1, default: false + t.text "comment", limit: 65535 t.datetime "created_at" t.datetime "updated_at" - t.text "comment" - t.string "status", limit: 255, default: "Ej bestämd" - t.boolean "service", default: false t.string "access_code", limit: 255 end - add_index "rents", ["d_from"], name: "index_rents_on_d_from" - add_index "rents", ["d_til"], name: "index_rents_on_d_til" + add_index "rents", ["d_from"], name: "index_rents_on_d_from", using: :btree + add_index "rents", ["d_til"], name: "index_rents_on_d_til", using: :btree create_table "roles", force: :cascade do |t| - t.string "name", limit: 255, null: false - t.string "title", limit: 255, null: false - t.text "description", null: false - t.text "the_role", null: false + t.string "name", limit: 255, null: false + t.string "title", limit: 255, null: false + t.text "description", limit: 65535, null: false + t.text "the_role", limit: 65535, null: false t.datetime "created_at" t.datetime "updated_at" end create_table "short_links", force: :cascade do |t| - t.string "link", limit: 255, null: false - t.text "target", null: false + t.string "link", limit: 255, null: false + t.text "target", limit: 65535, null: false end - add_index "short_links", ["link"], name: "index_short_links_on_link" + add_index "short_links", ["link"], name: "index_short_links_on_link", using: :btree + + create_table "subcategories", force: :cascade do |t| + t.string "text", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" + end create_table "users", force: :cascade do |t| t.string "username", limit: 255, null: false @@ -429,38 +409,35 @@ t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", limit: 4, default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" t.string "current_sign_in_ip", limit: 255 t.string "last_sign_in_ip", limit: 255 - t.integer "role_id", default: 2, null: false + t.integer "role_id", limit: 4, default: 2, null: false t.datetime "created_at" t.datetime "updated_at" end - add_index "users", ["email"], name: "index_users_on_email", unique: true - add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true - create_table "work_posts", force: :cascade do |t| t.string "title", limit: 255 - t.text "description" + t.text "description", limit: 65535 t.string "company", limit: 255 t.datetime "deadline" t.string "for", limit: 255 - t.boolean "visible" + t.boolean "visible", limit: 1 t.datetime "publish" t.string "picture_file_name", limit: 255 t.string "picture_content_type", limit: 255 - t.integer "picture_file_size" + t.integer "picture_file_size", limit: 4 t.datetime "picture_updated_at" - t.integer "responsible" + t.integer "responsible", limit: 4 t.datetime "created_at" t.datetime "updated_at" t.string "category", limit: 255 t.string "link", limit: 255 t.string "kind", limit: 255 - t.integer "row_order" + t.integer "row_order", limit: 4 end end diff --git a/app/assets/javascripts/loading_spinner.js.coffee b/lib/assets/javascripts/loading_spinner.js.coffee similarity index 100% rename from app/assets/javascripts/loading_spinner.js.coffee rename to lib/assets/javascripts/loading_spinner.js.coffee diff --git a/lib/tasks/tests_data.rake b/lib/tasks/tests_data.rake new file mode 100644 index 000000000..d8d65a03e --- /dev/null +++ b/lib/tasks/tests_data.rake @@ -0,0 +1,72 @@ +namespace :load_database do + desc 'Loads some stuff into the database for local testing' + task(populate: :environment) do + # Councils + pryl = Council.find_or_create_by!(title: 'Prylmästeriet', + url: 'pryl', description: 'Detta är Prylmästeriet', public: true) + sexm = Council.find_or_create_by!(title: 'Sexmästeriet', + url: 'sex', description: 'Detta är Sexmästeriet', public: true) + cafem = Council.find_or_create_by!(title: 'Cafemästeriet', + url: 'cafe', description: 'Detta är Cafemästeriet', public: true) + + # Posts + # Prylmästeriet + spindel = Post.find_or_create_by!(title: 'Spindelman', limit: 0, recLimit: 10, description: 'En administratör', + council: pryl, elected_by: 'Styrelsen', elected_at: 'VT', car_rent: true) + + prylmast = Post.find_or_create_by!(title: 'Prylmästare', limit: 1, recLimit: 1, + description: 'Prylmästarn', council: pryl, elected_by: 'Terminsmötet', + styrelse: true, elected_at: 'VT', car_rent: true) + # Sexmästeriet + Post.find_or_create_by!(title: 'Server', limit: 0, recLimit: 10, description: 'En serverare', + council: sexm, elected_by: 'Styrelsen', elected_at: 'HT') + + sexmast = Post.find_or_create_by!(title: 'Sexmästare', limit: 1, recLimit: 1, + description: 'Sexmästaren', council: sexm, elected_by: 'Terminsmötet', + styrelse: true, elected_at: 'VT', car_rent: true) + + # Cafemästeriet + Post.find_or_create_by!(title: 'Vice cafemästare', limit: 1, recLimit: 1, description: 'En vice cm', + council: cafem, elected_by: 'Terminsmötet', + styrelse: true, elected_at: 'HT', car_rent: true) + + cafemast = Post.find_or_create_by!(title: 'Cafemästare', limit: 1, recLimit: 1, + description: 'Cafemästaren', council: cafem, elected_by: 'Terminsmötet', + styrelse: true, elected_at: 'HT', car_rent: true) + nyckelpiga = Post.find_or_create_by!(title: 'Nyckelpiga', limit: 0, recLimit: 10, + description: 'Nyckelpigan!', council: cafem, elected_by: '') + + # Set president! + pryl.update(president: prylmast) + sexm.update(president: sexmast) + cafem.update(president: cafemast) + + # Permissions + Rake::Task['permissions:load'].invoke + perm_admin = Permission.find_or_create_by!(subject_class: :all, action: :manage) + perm_nyckelpiga = Permission.find_or_create_by!(subject_class: :cafe_work, action: :nyckelpiga) + # Give spindelman admin + PermissionPost.find_or_create_by!(permission: perm_admin, post: spindel) + PermissionPost.find_or_create_by!(permission: perm_nyckelpiga, post: nyckelpiga) + + u = User.find_or_initialize_by(username: 'user', email: 'david@da.vid') + u.password = 'passpass' + u.as_f_member.save! + if u.present? + p = u.profile + p.update!(name: 'David', lastname: 'Wessman', program: 'Teknisk Fysik', start_year: 2013) + if !p.posts.include?(spindel) + p.posts << spindel + end + if !p.posts.include?(prylmast) + p.posts << prylmast + end + if !p.posts.include?(cafemast) + p.posts << cafemast + end + if !p.posts.include?(sexmast) + p.posts << sexmast + end + end + end +end diff --git a/spec/controllers/admin/cafe_works_controller_spec.rb b/spec/controllers/admin/cafe_works_controller_spec.rb new file mode 100644 index 000000000..4379ed815 --- /dev/null +++ b/spec/controllers/admin/cafe_works_controller_spec.rb @@ -0,0 +1,143 @@ +require 'rails_helper' + +RSpec.describe Admin::CafeWorksController, type: :controller do + let(:user) { create(:user) } + let(:not_owner) { create(:user) } + let(:cwork_profile) { create(:cafe_work, :w_profile, profile: user.profile) } + let(:cwork_access) { create(:cafe_work, :access) } + let(:cwork) { create(:cafe_work) } + + before(:each) do + allow(controller).to receive(:current_user).and_return(user) + end + allow_user_to :manage, CafeWork + + describe 'GET #show' do + it 'assigns the requested cafe_work as @cwork' do + get :show, {id: cwork.to_param} + assigns(:cafe_work).should eq(cwork) + end + it 'error cafe_work is not found' do + lambda do + get :show, {id: 99997777} + end.should raise_error(ActionController::RoutingError) + end + end + + describe 'GET #new' do + it :succeeds do + get :new + + response.should be_success + end + it 'sets new cwork' do + get :new + + assigns(:cafe_work).should be_an_instance_of(CafeWork) + assigns(:cafe_work).new_record?.should be_truthy + end + end + + describe 'GET #edit' do + it 'assigns the requested cafe_work as @cwork' do + get :edit, {id: cwork.to_param} + + assigns(:cafe_work).should eq(cwork) + end + it 'succeeds' do + get :edit, {id: cwork.to_param} + + response.should be_success + end + end + + describe 'POST #create' do + it 'new cafe work' do + lambda { post :create, cafe_work: {lv: 1, lp: 1, work_day: Time.zone.now, pass: 1, controller: ''} }.should change(CafeWork, :count).by(1) + + response.should redirect_to([:admin, CafeWork.last]) + end + end + + describe 'PATCH #update' do + context 'with valid params' do + let(:attr) { attributes_for(:cafe_work, :tester) } + it 'updates the requested cafe work' do + patch :update, id: cwork.to_param, cafe_work: attr + cwork.reload + (cwork.pass == attr[:pass] && + cwork.lv == attr[:lv] && + cwork.lp == attr[:lp]).should be_truthy + end + + it 'assigns the requested cwork and redirects ' do + patch :update, id: cwork.to_param, cafe_work: attr + + assigns(:cafe_work).should eq(cwork) + response.should redirect_to([:admin, cwork]) + end + end + + context 'with invalid params' do + let(:attr) { attributes_for(:cafe_work, :invalid) } + it 'assigns the candidate as @candidate' do + patch :update, id: cwork.to_param, cafe_work: attr + + assigns(:cafe_work).should eq(cwork) + end + + it 're-renders the edit-template' do + patch :update, id: cwork.to_param, cafe_work: attr + + response.should render_template(:edit) + end + end + end + + describe 'DELETE #destroy' do + before { cwork } + it 'destroys the requested cwork' do + lambda { delete :destroy, id: cwork.to_param, format: :html }.should change(CafeWork, :count).by(-1) + end + + it 'redirects to the candidates list' do + delete :destroy, id: cwork.to_param + response.should redirect_to(:admin_hilbert) + end + + it 'assigns the requested id' do + xhr :delete, :destroy, id: cwork.to_param + + assigns(:id).should eq(cwork.id) + end + end + + describe 'PATCH #remove_worker' do + it 'remove worker with profile' do + xhr :patch, :remove_worker, {id: cwork_profile.to_param} + cwork_profile.reload + + cwork_profile.has_worker?.should be_falsey + end + end + + describe 'GET #setup' do + it 'assigns @cafe_work as new record' do + get :setup + assigns(:cafe_work).new_record?.should be_truthy + end + end + + describe 'POST #setup_create' do + # Should use a more precise method + it 'preview post' do + post :setup_create, {commit: 'Förhandsgranska', cafe_work: attributes_for(:cafe_work), lv_first: 1, lv_last: 1} + assigns(:cafe_works).count.should eq(CafeSetupWeek.new(cwork.work_day, cwork.lp).preview(1, 1).count) + end + it 'create post' do + lambda { + post :setup_create, {commit: 'Spara', cafe_work: attributes_for(:cafe_work), lv_first: 1, lv_last: 1} + }.should change(CafeWork, :count).by(20) + end + end +end diff --git a/spec/controllers/cafe_works_controller_spec.rb b/spec/controllers/cafe_works_controller_spec.rb new file mode 100644 index 000000000..8c04859df --- /dev/null +++ b/spec/controllers/cafe_works_controller_spec.rb @@ -0,0 +1,210 @@ +require 'rails_helper' + +RSpec.describe CafeWorksController, type: :controller do + let(:user) { create(:user) } + let(:not_owner) { create(:user) } + let(:cwork_profile) { create(:cafe_work, :w_profile, profile: user.profile) } + let(:cwork_access) { create(:cafe_work, :access) } + let(:cwork) { create(:cafe_work) } + + allow_user_to [:show, :index, :update_worker, :remove_worker, :authorize], CafeWork + + describe 'GET #show' do + it 'assigns the requested cafe_work as @cwork' do + get :show, {id: cwork.to_param} + assigns(:cafe_work).should eq(cwork) + end + end + + describe 'POST #authorize' do + it 'authorizes with right code' do + xhr :post, :authorize, {id: cwork_access.to_param, cafe_work: {access_code: cwork_access.access_code}} + + assigns(:cafe_work).should eq(cwork_access) + assigns(:authenticated).should be_truthy + end + + it 'authorizes with wrong code' do + xhr :post, :authorize, {id: cwork_access.to_param, cafe_work: {access_code: 'wrong code'}} + + assigns(:authenticated).should be_falsey + end + end + + describe 'PATCH #update_worker' do + context 'with valid params' do + context 'valid user' do + before { allow(controller).to receive(:current_user).and_return(user) } + it 'add worker' do + patch :update_worker, {id: cwork.to_param, cafe_work: attributes_for(:assignee)} + cwork.reload + + cwork.has_worker?.should be_truthy + end + + it 'update worker' do + patch :update_worker, {id: cwork_profile.to_param, cafe_work: attributes_for(:assignee, :test)} + cwork_profile.reload + + cwork_profile.worker.attributes.should include(attributes_for(:assignee, :test)) + end + + it 'assigns the requested cafe_work as @cafe_work' do + patch :update_worker, {id: cwork.to_param, cafe_work: attributes_for(:assignee)} + + assigns(:cafe_work).should eq(cwork) + end + + it 'redirects to the cafe_work' do + patch :update_worker, {id: cwork.to_param, cafe_work: attributes_for(:assignee)} + + response.should redirect_to(cwork) + end + end + + context 'invalid user' do + before do + allow(controller).to receive(:current_user).and_return(not_owner) + end + + it 'update worker' do + patch :update_worker, {id: cwork_profile.to_param, cafe_work: attributes_for(:assignee, :test)} + cwork_profile.reload + + cwork_profile.worker.attributes.should_not include(attributes_for(:assignee, :test)) + end + + it 'redirects to the cafe_work' do + patch :update_worker, {id: cwork_profile.to_param, cafe_work: attributes_for(:assignee)} + + response.should render_template('show') + end + end + + context 'with no user' do + it 'update worker' do + patch :update_worker, + { + id: cwork_access.to_param, + cafe_work: attributes_for(:assignee, :test, access_code: cwork_access.access_code) + } + cwork_access.reload + + cwork_access.worker.attributes.should include(attributes_for(:assignee, :test)) + end + + it 'redirects to the cafe_work' do + patch :update_worker, + { + id: cwork_access.to_param, + cafe_work: attributes_for(:assignee, access_code: cwork_access.access_code) + } + + response.should redirect_to(cwork_access) + end + end + end + + context 'with invalid params' do + it 'assigns the cafe_work as @cafe_work' do + patch :update_worker, {id: cwork.to_param, cafe_work: attributes_for(:assignee, :invalid)} + assigns(:cafe_work).should eq(cwork) + response.should render_template('show') + end + end + end + + describe 'PATCH #remove_worker' do + context 'with valid user' do + before do + allow(controller).to receive(:current_user).and_return(user) + end + it 'remove worker with profile' do + patch :remove_worker, {id: cwork_profile.to_param} + cwork_profile.reload + + cwork_profile.has_worker?.should be_falsey + end + + it 'remove worker with profile and redirect' do + patch :remove_worker, {id: cwork_profile.to_param} + cwork_profile.reload + + response.should redirect_to(cwork_profile) + end + + it 'assigns the requested cafe_work as @cafe_work' do + patch :remove_worker, {id: cwork_profile.to_param} + + assigns(:cafe_work).should eq(cwork_profile) + end + end + + context 'with invalid user' do + before do + allow(controller).to receive(:current_user).and_return(not_owner) + end + + it 'remove worker' do + patch :remove_worker, {id: cwork_profile.to_param} + cwork_profile.reload + + cwork_profile.worker.present?.should be_truthy + response.should render_template(:show) + end + end + + context 'with no user' do + it 'remove worker' do + patch :remove_worker, + { + id: cwork_access.to_param, + cafe_work: {access_code: cwork_access.access_code} + } + cwork_access.reload + + cwork_access.worker.present?.should be_falsey + response.should redirect_to(cwork_access) + end + end + end + + describe 'GET #index' do + it 'renders #index' do + get :index + response.should render_template(:index) + end + it 'assigns CafeWork.lv as @lv' do + get :index + assigns(:lv).should eq(CafeWork.get_lv) + end + before { + cwork + cwork_profile + } + it 'responds with JSON' do + get :index, {start: cwork.work_day - 2.days, end: cwork.work_day + 2.days, format: :json} + response.body.should eq([cwork.as_json, cwork_profile.as_json].to_json) + end + end + + describe 'GET #nyckelpiga' do + context 'not allowed' do + it 'does not work' do + get :nyckelpiga + response.should have_http_status(:forbidden) + end + end + context 'allowed' do + before do + ability = Ability.new(user) + ability.can :nyckelpiga, CafeWork + allow(controller).to receive(:current_ability).and_return(ability) + end + it 'works' do + get :nyckelpiga + response.should be_success + end + end + end +end diff --git a/spec/factories/assignees.rb b/spec/factories/assignees.rb new file mode 100644 index 000000000..ada865b57 --- /dev/null +++ b/spec/factories/assignees.rb @@ -0,0 +1,23 @@ +# encoding: UTF-8 +FactoryGirl.define do + factory :assignee do + name + lastname + email + phone + + trait :test do + name 'Test' + lastname 'Testaren' + email 'tests@tes.t' + phone '7357' + end + + trait :invalid do + name '' + lastname '' + email '' + phone '' + end + end +end diff --git a/spec/factories/cafe_work_councils.rb b/spec/factories/cafe_work_councils.rb new file mode 100644 index 000000000..aff038aae --- /dev/null +++ b/spec/factories/cafe_work_councils.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do + factory :cafe_work_council do + cafe_work + council + end +end diff --git a/spec/factories/cafe_works.rb b/spec/factories/cafe_works.rb new file mode 100644 index 000000000..cecb14ce0 --- /dev/null +++ b/spec/factories/cafe_works.rb @@ -0,0 +1,50 @@ +# encoding: UTF-8 +FactoryGirl.define do + factory :cafe_work do + pass { rand(1..4) } + lv { rand(1..7) } + lp { rand(1..4) } + d_year { Time.zone.now.year } + work_day { Time.zone.now + 10.day } + + trait :tester do + pass 1 + lv 7 + lp 4 + end + + trait :invalid do + pass -5 + lv 1337 + lp 6122 + end + + trait :test_work do + name 'Test' + lastname 'Testet' + email 'test@test.se' + phone '0705507889' + end + + trait :worker do + name + lastname + email + phone + end + + trait :w_profile do + worker + profile + access_code nil + end + + trait :access do + worker + profile nil + access_code + end + end + + +end diff --git a/spec/factories/constant.rb b/spec/factories/constants.rb similarity index 56% rename from spec/factories/constant.rb rename to spec/factories/constants.rb index 185845613..16afca097 100644 --- a/spec/factories/constant.rb +++ b/spec/factories/constants.rb @@ -1,5 +1,6 @@ +#encoding: UTF-8 FactoryGirl.define do - factory :constant do |c| + factory :constant do name value end diff --git a/spec/factories/councils.rb b/spec/factories/councils.rb index 0cf0e58e0..688d3d79d 100644 --- a/spec/factories/councils.rb +++ b/spec/factories/councils.rb @@ -3,5 +3,21 @@ factory :council do title url + + trait :with_page do + after(:create) do |council| + create(:page, council: council) + end + end + + trait :with_posts do + transient do + post_count 3 + end + + after(:create) do |council, evaluator| + create_list(:post, evaluator.post_count, council: council) + end + end end -end \ No newline at end of file +end diff --git a/spec/factories/page_elements.rb b/spec/factories/page_elements.rb new file mode 100644 index 000000000..4cb52b3ca --- /dev/null +++ b/spec/factories/page_elements.rb @@ -0,0 +1,10 @@ +# encoding: UTF-8 +FactoryGirl.define do + factory :page_element do + page + displayIndex { rand(1..10) } + sidebar { [true, false].sample } + visible true + text { generate(:description) } + end +end diff --git a/spec/factories/pages.rb b/spec/factories/pages.rb new file mode 100644 index 000000000..d37cea4a3 --- /dev/null +++ b/spec/factories/pages.rb @@ -0,0 +1,16 @@ +# encoding: UTF-8 +FactoryGirl.define do + factory :page do + council + + factory :page_with_elements do + transient do + element_count 3 + end + + after(:create) do |page, evaluator| + create_list(:page_element, evaluator.element_count, page: page) + end + end + end +end diff --git a/spec/factories/rents.rb b/spec/factories/rents.rb index 9832d2f7c..712d8271e 100644 --- a/spec/factories/rents.rb +++ b/spec/factories/rents.rb @@ -6,6 +6,8 @@ lastname email phone + disclaimer true + purpose 'Handla möbler på IKEA' d_from { Time.zone.now + 10.day } d_til { Time.zone.now + 10.day + 12.hours } @@ -27,12 +29,8 @@ aktiv true end - trait :disclaimer do - disclaimer true - end - trait :confirmed do - status "Bekräftad" + status 'Bekräftad' end trait :over_48 do @@ -44,16 +42,19 @@ end trait :purpose do - purpose "Handla möbler på IKEA" + purpose 'Handla möbler på IKEA' end - trait :service do + trait :services do service true end trait :comment do - comment "Du har uppebarligen inget körkort" + comment 'Du har uppebarligen inget körkort' end - factory :good_rent, parent: :rent, traits: [:with_profile, :disclaimer, :active, :purpose] -end \ No newline at end of file + trait :good do + profile + aktiv true + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index f9de193df..a1d5a8738 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -1,11 +1,26 @@ +# encoding: UTF-8 FactoryGirl.define do factory :user do username - password '12345678' email - profile + password '12345678' before(:create) { |user| user.as_f_member } - after(:create) { |user| create(:profile, user: user) } + + # Overrides the :create_profile_for_user method + after(:build) { |user| user.class.skip_callback(:create, :after, :create_profile_for_user) } + + # Uses profiles factory to create a valid profile + after(:create) do |user, evaluator| + create(:profile, user: user) + end + + # Can be called to create a user with the :create_profile_for_user method + trait :user_with_create_profile do + after(:create) { |user| user.send(:create_profile_for_user) } + end + + # Needed because users cannot be created without f_validate being okay. + to_create { |instance| instance.save!(validate: false) } end factory :admin, class: 'User' do diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 5989377dc..74720c513 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -2,30 +2,27 @@ require 'cancan/matchers' describe Ability do - context 'not_signed_in' do - subject(:ability) { Ability.new(nil) } - - # Stuff everyone can do + subject(:ability) { Ability.new(user) } + context 'no user' do + let(:user) { nil } it { should be_able_to :read, News.new } - - # Stuff everyone must not be able to do - it { should_not be_able_to :read, Constant.new } - it { should_not be_able_to :read, Album.new } - it { should_not be_able_to :read, Post.new } - it { should_not be_able_to :read, Event.new } - it { should_not be_able_to :read, Candidate.new } - it { should_not be_able_to :read, Permission.new } - it { should_not be_able_to :read, Profile.new } - it { should_not be_able_to :read, User.new } + it { should be_able_to :read, Council.new } + it { should be_able_to :read, CafeWork.new } end context 'default user' do - let(:user) { FactoryGirl.create(:user) } - let(:ability) { FactoryGirl.create(:user) } + let(:user) { create(:user) } + let(:ability) { create(:user) } subject(:ability) { Ability.new(user) } # Stuff everyone can do + it { should be_able_to :read, Event.new } + it { should be_able_to :read, Council.new } + it { should be_able_to :read, CafeWork.new } it { should be_able_to :read, News.new } + it { should be_able_to :read, Post.new } + it { should be_able_to :read, Election.new } + # Stuff everyone must not be able to do it { should_not be_able_to :read, Constant.new } @@ -37,9 +34,7 @@ end context 'admin user' do - let(:user) { FactoryGirl.create(:admin) } - let(:ability) { FactoryGirl.create(:user) } - subject(:ability) { Ability.new(user) } + let(:user) { create(:admin) } # Can do anything it { should be_able_to :manage, :all } diff --git a/spec/models/cafe_work_council_spec.rb b/spec/models/cafe_work_council_spec.rb new file mode 100644 index 000000000..1064142c2 --- /dev/null +++ b/spec/models/cafe_work_council_spec.rb @@ -0,0 +1,8 @@ +require 'rails_helper' + +RSpec.describe CafeWorkCouncil, type: :model do + it { should validate_presence_of(:cafe_work) } + it { should validate_presence_of(:council) } + it { should belong_to(:cafe_work) } + it { should belong_to(:council) } +end diff --git a/spec/models/cafe_work_spec.rb b/spec/models/cafe_work_spec.rb new file mode 100644 index 000000000..6983874f6 --- /dev/null +++ b/spec/models/cafe_work_spec.rb @@ -0,0 +1,159 @@ +require 'rails_helper' + +RSpec.describe CafeWork, type: :model do + it "has a valid factory" do + (build(:cafe_work)).should be_valid + end + + let(:user) { create(:user)} + let(:not_owner) { create(:user)} + let(:cwork_profile) { create(:cafe_work, :w_profile, profile: user.profile) } + let(:cwork_access) { create(:cafe_work, :access) } + let(:cwork_no_worker) { create(:cafe_work) } + subject(:cwork) { build(:cafe_work) } + + describe 'ActiveModel validations' do + # Basic validations + it { should validate_presence_of(:work_day) } + it { should validate_presence_of(:pass) } + it { should validate_presence_of(:lp) } + it { should validate_presence_of(:lv) } + it { should validate_inclusion_of(:pass).in_range(1..4) } + it { should validate_inclusion_of(:lp).in_range(1..4) } + it { should validate_inclusion_of(:lv).in_range(1..7) } + + context 'if has_worker' do + before { allow(subject).to receive(:has_worker?).and_return(true) } + it { subject.should validate_presence_of(:name) } + it { subject.should validate_presence_of(:lastname) } + it { subject.should validate_presence_of(:phone) } + it { subject.should validate_presence_of(:email) } + end + + end + + describe "ActiveRecord associations" do + # Associations + it { should belong_to(:profile) } + it { should have_many(:cafe_work_councils) } + it { should have_many(:councils) } + end + + describe "public instance methods" do + context "responds to its methods" do + it { should respond_to(:send_email) } + it { should respond_to(:load) } + it { should respond_to(:status_text) } + it { should respond_to(:status_view) } + it { should respond_to(:add_or_update) } + it { should respond_to(:add_worker) } + it { should respond_to(:update_worker) } + it { should respond_to(:remove_worker) } + it { should respond_to(:clear_worker) } + it { should respond_to(:owner?) } + it { should respond_to(:edit?) } + it { should respond_to(:authorize) } + it { should respond_to(:has_worker?) } + it { should respond_to(:print_time) } + it { should respond_to(:print) } + it { should respond_to(:print_date) } + it { should respond_to(:p_url) } + it { should respond_to(:p_path) } + it { should respond_to(:as_json) } + it { should respond_to(:start) } + it { should respond_to(:stop) } + end + + context "executes methods correctly" do + let(:user) { create(:user) } + context "has_worker" do + it 'do not have worker if profile and access_code is nil' do + cwork_profile.clear_worker + (cwork_profile.has_worker?).should be_falsey + end + it 'do have worker if profile is not nil' do + (cwork_profile.has_worker?).should be_truthy + end + it 'do have worker if access_code is not nil' do + (cwork_access.has_worker?).should be_truthy + end + end + + context "add_worker" do + it 'add worker with params and no user' do + cwork_no_worker.add_worker(attributes_for(:assignee), nil) + (cwork_no_worker.has_worker?).should be_truthy + end + it 'add worker with params and no user, has access_code' do + cwork_no_worker.add_worker(attributes_for(:assignee), nil) + (cwork_no_worker.access_code).should_not be_nil + end + it 'add worker with params and with user' do + cwork_no_worker.add_worker(attributes_for(:assignee), user) + (cwork_no_worker.has_worker?).should be_truthy + end + it 'add worker with params and user, have profile' do + cwork_no_worker.add_worker(attributes_for(:assignee), user) + (cwork_no_worker.profile).should eq(user.profile) + end + end + + context "remove_worker" do + it 'with the right user' do + cwork_profile.remove_worker(user, nil) + (cwork_no_worker.worker.profile).should be_nil + end + it 'with the wrong user' do + cwork_profile.remove_worker(not_owner, nil) + (cwork_profile.worker.profile).should_not be_nil + end + it 'with right access_code' do + access = cwork_access.access_code + cwork_access.remove_worker(nil, access) + (cwork_access.has_worker?).should be_falsey + end + it 'with right access_code' do + access = 'wrong code' + cwork_access.remove_worker(nil, access) + (cwork_access.has_worker?).should be_truthy + end + end + + context 'update_worker' do + it 'update worker with user' do + cwork_profile.profile = user.profile + cwork_profile.update_worker(attributes_for(:assignee, lastname: 'Wessman'), user) + (cwork_profile.lastname).should eq('Wessman') + end + end + + context 'status_view' do + it 'should return :sign_up for cwork' do + cwork_no_worker.status_view(nil).should eq(:sign_up) + end + it 'should return :edit for cwork_profile' do + cwork_profile.status_view(user).should eq(:edit) + end + it 'should return :authorize for cwork_profile' do + cwork_access.status_view(user).should eq(:authorize) + end + it 'should return :assigned for cwork_profile' do + cwork_profile.status_view(not_owner).should eq(:assigned) + end + end + end + # This tests makes sure that dates are formatted into ISO8601 for + # Fullcalendars json-feed + # Ref.: https://github.com/fsek/web/issues/99 + # /d.wessman + describe :Json do + it 'check date format is iso8601' do + (cwork_profile.as_json.to_json).should include(cwork_profile.start.iso8601.to_json) + (cwork_profile.as_json.to_json).should include(cwork_profile.stop.iso8601.to_json) + end + it 'as_json request is processed with parameters' do + (cwork_profile.as_json('params').to_json).should include(cwork_profile.start.iso8601.to_json) + end + end + end +end diff --git a/spec/models/constant_spec.rb b/spec/models/constant_spec.rb index ade5e47df..045c5c64c 100644 --- a/spec/models/constant_spec.rb +++ b/spec/models/constant_spec.rb @@ -1,12 +1,18 @@ require 'rails_helper' RSpec.describe Constant, type: :model do - it { should validate_presence_of(:name) } - it { should validate_presence_of(:name) } + subject(:constant) { build(:constant) } + describe :Validations do + it { should validate_presence_of(:name) } + it { should validate_presence_of(:value) } + it { should validate_uniqueness_of(:name) } + end + it 'is valid with a name and a value' do c = Constant.new(name: 'foo', value: 'bar') expect(c).to be_valid end + it 'can return value by calling the get() function' do Constant.create(name: 'foo', value: 'bar') val = Constant.get 'foo' diff --git a/spec/models/rent_spec.rb b/spec/models/rent_spec.rb index 246c32ddd..0ddbd999c 100644 --- a/spec/models/rent_spec.rb +++ b/spec/models/rent_spec.rb @@ -2,8 +2,11 @@ require 'rails_helper' RSpec.describe Rent, type: :model do - subject(:rent) { FactoryGirl.build(:rent) } - let(:rental) { create(:good_rent)} + subject(:rent) { build(:rent) } + let(:saved) { create(:rent, :good) } + describe 'has valid factory' do + it { should be_valid } + end describe :Associations do it { should belong_to(:profile) } @@ -11,7 +14,6 @@ end describe :Validations do - # Disclaimer it { should allow_value(true).for(:disclaimer) } it { should_not allow_value(false).for(:disclaimer) } @@ -35,253 +37,199 @@ end end - # Some tests for the duration method - # /d.wessman describe :Duration do context :when_no_council do it 'add error if duration is over 48' do - rent = FactoryGirl.build(:rent, :over_48) + rent = build(:rent, :over_48) rent.valid? - expect(rent.errors.get(:d_from)).to include(", får inte vara längre än 48 h") + rent.errors.get(:d_from).should include(', får inte vara längre än 48 h') end it 'do not add error if duration is under 48' do - rent = FactoryGirl.build(:rent, :under_48) + rent = build(:rent, :under_48) rent.valid? - expect(rent.errors.get(:d_from)).to be_nil or not_include(", får inte vara längre än 48 h") + rent.errors.get(:d_from).should be_nil or not_include(', får inte vara längre än 48 h') end it 'valid when duration is under 48' do - rent = FactoryGirl.build(:good_rent, :under_48) - expect(rent).to be_valid + rent = build(:rent, :good, :under_48) + rent.should be_valid end end context :when_council do it 'do not add error if duration is over 48' do - rent = FactoryGirl.build(:rent, :over_48, :with_council) + rent = build(:rent, :over_48, :with_council) rent.valid? - expect(rent.errors.get(:d_from)).to be_nil or not_include(", får inte vara längre än 48 h") + rent.errors.get(:d_from).should be_nil end it 'do not add error if duration is under 48' do - rent = FactoryGirl.build(:rent, :under_48, :with_council) + rent = build(:rent, :under_48, :with_council) rent.valid? - expect(rent.errors.get(:d_from)).to be_nil or not_include(", får inte vara längre än 48 h") + rent.errors.get(:d_from).should be_nil end it 'valid for any duration' do - rent = FactoryGirl.build(:good_rent, :over_48, :with_council) - expect(rent).to be_valid + rent = build(:rent, :good, :over_48, :with_council) + rent.should be_valid end end end - # Test to make sure rent is in future - # /d.wessman describe :Dates_in_future do context :when_future do it 'add error if d_from > d_til' do - rent = FactoryGirl.build(:rent) rent.d_from = rent.d_til + 1.hour rent.valid? - expect(rent.errors.get(:d_til)).to include("måste vara efter startdatumet.") + rent.errors.get(:d_til).should include('måste vara efter startdatumet.') end it 'do not add error if d_from < d_til ' do - rent = FactoryGirl.build(:rent) rent.valid? - expect(rent.errors.get(:d_til)).to be_nil or not_include("måste vara efter startdatumet.") - end - it 'no other validation failing' do - rent = FactoryGirl.build(:good_rent) - expect(rent).to be_valid + rent.errors.get(:d_til).should be_nil end end context :when_past do it 'add error if d_from > d_til' do - rent = FactoryGirl.build(:rent) rent.d_til = Time.zone.now - 10.hours rent.d_from = rent.d_til + 5.hours rent.valid? - expect(rent.errors.get(:d_til)).to include("måste vara efter startdatumet.") + rent.errors.get(:d_til).should include("måste vara efter startdatumet.") end it 'add error if d_from > d_til' do - rent = FactoryGirl.build(:rent) rent.d_til = Time.zone.now - 10.hours rent.d_from = rent.d_til + 5.hours rent.valid? - expect(rent.errors.get(:d_from)).to include("måste vara i framtiden.") + rent.errors.get(:d_from).should include("måste vara i framtiden.") end it 'add error if d_from < d_til' do - rent = FactoryGirl.build(:rent) rent.d_from = Time.zone.now - 10.hours rent.d_til = rent.d_from + 5.hours rent.valid? - expect(rent.errors.get(:d_from)).to include("måste vara i framtiden.") + rent.errors.get(:d_from).should include("måste vara i framtiden.") end end end - - - # Validate if overlap - # /d.wessman describe :Overlap do context :when_no_councils do + let(:overlap) { create(:rent, :good) } + let(:normal) { build(:rent, :good) } it 'invalid when d_til is within saved rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_from - 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to_not be_valid + normal.d_from = overlap.d_from - 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should_not be_valid end it 'invalid when d_from and d_til is within saved rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_from + 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to_not be_valid + normal.d_from = overlap.d_from + 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should_not be_valid end - it 'do add error if d_from is within saved' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_from + 5.hours - rent.d_til = overlap.d_til - 5.hours - rent.valid? - expect(rent.errors.get(:d_from)).to include("överlappar med annan bokning") + it 'add error if d_from is within saved' do + normal.d_from = overlap.d_from + 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.valid?.should be_falsey + normal.errors.get(:d_from).should include("överlappar med annan bokning") end it 'invalid when d_from is within saved rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_til - 5.hours - rent.d_til = overlap.d_til + 5.hours - expect(rent).to_not be_valid + normal.d_from = overlap.d_til - 5.hours + normal.d_til = overlap.d_til + 5.hours + normal.should_not be_valid end it 'do add error if d_from is within saved' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_til - 5.hours - rent.d_til = overlap.d_til + 5.hours - rent.valid? - expect(rent.errors.get(:d_from)).to include("överlappar med annan bokning") + normal.d_from = overlap.d_til - 5.hours + normal.d_til = overlap.d_til + 5.hours + normal.valid? + normal.errors.get(:d_from).should include("överlappar med annan bokning") end it 'valid when d_from and d_til is outside saved rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_til + 5.hours - rent.d_til = rent.d_from + 5.hours - expect(rent).to be_valid + normal.d_from = overlap.d_til + 5.hours + normal.d_til = normal.d_from + 5.hours + normal.should be_valid end it 'do not add error if d_til and d_from is outside saved' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_til + 5.hours - rent.d_til = rent.d_from + 5.hours - rent.valid? - expect(rent.errors.get(:d_from)).to be_nil or not_include("överlappar med annan bokning") + normal.d_from = overlap.d_til + 5.hours + normal.d_til = normal.d_from + 5.hours + normal.valid? + normal.errors.get(:d_from).should be_nil end end + context :when_first_council_second_not do - it 'invalid when d_til is within good rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_from - 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to_not be_valid - end - it 'add error if d_til within saved' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_from - 5.hours - rent.d_til = overlap.d_til - 5.hours - rent.valid? - expect(rent.errors.get(:d_from)).to include("överlappar med annan bokning") - end - it 'invalid when d_from and d_til is within saved' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_from + 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to_not be_valid - end - it 'invalid when d_from is within saved rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_til - 5.hours - rent.d_til = overlap.d_til + 5.hours - expect(rent).to_not be_valid - end - it 'valid when d_from and d_til is outside saved rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent) - rent.d_from = overlap.d_til + 5.hours - rent.d_til = rent.d_from + 5.hours - expect(rent).to be_valid - end + let(:overlap) { create(:rent, :good, :with_council) } + let(:normal) { build(:rent, :good) } + it 'invalid when d_til is within' do + normal.d_from = overlap.d_from - 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should_not be_valid + normal.errors.get(:d_from).should include('överlappar med annan bokning') + end + it 'invalid when d_from and d_til is within saved' do + normal.d_from = overlap.d_from + 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should_not be_valid + end + it 'invalid when d_from is within saved rent' do + normal.d_from = overlap.d_til - 5.hours + normal.d_til = overlap.d_til + 5.hours + normal.should_not be_valid + end + it 'valid when d_from and d_til is outside saved rent' do + normal.d_from = overlap.d_til + 5.hours + normal.d_til = normal.d_from + 5.hours + normal.should be_valid + end end context :when_second_council_first_not do - it 'valid when d_til is within good rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_from - 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to be_valid - end - it 'valid when d_from and d_til is within good rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_from + 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to be_valid - end - it 'valid when d_from is within good rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_til - 5.hours - rent.d_til = overlap.d_til + 5.hours - expect(rent).to be_valid - end - it 'valid when d_from and d_til is outside good rent' do - overlap = FactoryGirl.create(:good_rent) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_til + 5.hours - rent.d_til = rent.d_from + 5.hours - expect(rent).to be_valid - end + let(:overlap) { create(:rent, :good) } + let(:normal) { build(:rent, :good, :with_council) } + it 'valid when d_til is within good rent' do + normal.d_from = overlap.d_from - 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should be_valid + end + it 'valid when d_from and d_til is within good rent' do + normal.d_from = overlap.d_from + 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should be_valid + end + it 'valid when d_from is within good rent' do + normal.d_from = overlap.d_til - 5.hours + normal.d_til = overlap.d_til + 5.hours + normal.should be_valid + end + it 'valid when d_from and d_til is outside good rent' do + normal.d_from = overlap.d_til + 5.hours + normal.d_til = normal.d_from + 5.hours + normal.should be_valid + end end + context :when_two_councils do + let(:overlap) { create(:rent, :good, :with_council) } + let(:normal) { build(:rent, :good, :with_council) } it 'invalid when d_til is within good rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_from - 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to_not be_valid + normal.d_from = overlap.d_from - 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should_not be_valid end it 'do add error if d_til within saved' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_from - 5.hours - rent.d_til = overlap.d_til + 5.hours - rent.valid? - expect(rent.errors.get(:d_from)).to include("överlappar med annan utskottsbokning") + normal.d_from = overlap.d_from - 5.hours + normal.d_til = overlap.d_til + 5.hours + normal.valid? + normal.errors.get(:d_from).should include('överlappar med annan utskottsbokning') end it 'invalid when d_from and d_til is within good rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_from + 5.hours - rent.d_til = overlap.d_til - 5.hours - expect(rent).to_not be_valid + normal.d_from = overlap.d_from + 5.hours + normal.d_til = overlap.d_til - 5.hours + normal.should_not be_valid end it 'invalid when d_from is within good rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_til - 5.hours - rent.d_til = overlap.d_til + 5.hours - expect(rent).to_not be_valid + normal.d_from = overlap.d_til - 5.hours + normal.d_til = overlap.d_til + 5.hours + normal.should_not be_valid end it 'valid when d_from and d_til is outside good rent' do - overlap = FactoryGirl.create(:good_rent,:with_council) - rent = FactoryGirl.build(:good_rent,:with_council) - rent.d_from = overlap.d_til + 5.hours - rent.d_til = rent.d_from + 5.hours - expect(rent).to be_valid + normal.d_from = overlap.d_til + 5.hours + normal.d_til = normal.d_from + 5.hours + normal.should be_valid end end end @@ -291,8 +239,8 @@ # /d.wessman describe :Json do it 'check date format is iso8601' do - (rental.as_json.to_json).should include(rental.d_from.iso8601.to_json) - (rental.as_json.to_json).should include(rental.d_til.iso8601.to_json) + (saved.as_json.to_json).should include(saved.d_from.iso8601.to_json) + (saved.as_json.to_json).should include(saved.d_til.iso8601.to_json) end end end diff --git a/spec/model/short_link_spec.rb b/spec/models/short_link_spec.rb similarity index 100% rename from spec/model/short_link_spec.rb rename to spec/models/short_link_spec.rb diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 2c26b741e..b6f31dff2 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -28,12 +28,19 @@ RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + #config.fixture_path = "#{::Rails.root}/spec/fixtures" # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. config.use_transactional_fixtures = false + config.include FactoryGirl::Syntax::Methods + + # Uncomment this line when all tests are rewritten with should-syntax + # Ref: https://github.com/fsek/web/issues/68 + # Right now it is failing many tests because they have expect-syntax + # /d.wessman + #config.expect_with(:rspec) { |c| c.syntax = :should } # RSpec Rails can automatically mix in different behaviours to your tests # based on their file location, for example enabling you to call `get` and diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8f3e38006..d59613b08 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -23,16 +23,14 @@ require 'rails/all' require 'rspec/rails' require 'capybara/rspec' - -Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } +require 'capybara/rails' # I had to include this, /d.wessman 2015-03-20 require 'database_cleaner' # Devise helpers require 'devise' -Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } - +Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } RSpec.configure do |config| config.include Devise::TestHelpers, type: 'controller' config.extend ControllerMacros, type: 'controller' @@ -40,7 +38,7 @@ # Uncomment when all tests uses should #expectations.syntax = :should expectations.include_chain_clauses_in_custom_matcher_descriptions = true - expectations.syntax = [ :should, :expect ] + expectations.syntax = [:should, :expect] end config.mock_with :rspec do |mocks| diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb index 49441790d..f1aab3f2d 100644 --- a/spec/support/database_cleaner.rb +++ b/spec/support/database_cleaner.rb @@ -1,10 +1,13 @@ -#encoding: UTF-8 - +# encoding: UTF-8 require 'database_cleaner' RSpec.configure do |config| config.before(:suite) do - DatabaseCleaner.clean_with :deletion + DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean_with(:truncation) + end + config.before(:suite) do + DatabaseCleaner.clean_with(:deletion) end config.before(:each) do diff --git a/spec/support/factory_girl.rb b/spec/support/factory_girl.rb index d7c757f3c..d282e75a9 100644 --- a/spec/support/factory_girl.rb +++ b/spec/support/factory_girl.rb @@ -2,11 +2,13 @@ config.include FactoryGirl::Syntax::Methods config.before(:suite) do - # Do not lint rent because it fails - # See https://github.com/fsek/web/issues/72 + + # Do not lint assignee, it is not ActiveRecord + # /d.wessman factories_to_lint = FactoryGirl.factories.reject do |factory| - factory.name =~ /^rent/ + factory.name =~ /assignee/ end + begin DatabaseCleaner.start FactoryGirl.lint factories_to_lint diff --git a/vendor/assets/javascripts/bootstrap-datetimepicker.js b/vendor/assets/javascripts/bootstrap-datetimepicker.js new file mode 100644 index 000000000..02e0ff14d --- /dev/null +++ b/vendor/assets/javascripts/bootstrap-datetimepicker.js @@ -0,0 +1,1941 @@ +/* + //! version : 4.3.5 + ========================================================= + bootstrap-datetimejs + https://github.com/Eonasdan/bootstrap-datetimepicker + ========================================================= + The MIT License (MIT) + + Copyright (c) 2015 Jonathan Peterson + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +/*global define:false */ +/*global exports:false */ +/*global require:false */ +/*global jQuery:false */ +/*global moment:false */ +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // AMD is used - Register as an anonymous module. + define(['jquery', 'moment'], factory); + } else if (typeof exports === 'object') { + factory(require('jquery'), require('moment')); + } else { + // Neither AMD nor CommonJS used. Use global variables. + if (typeof jQuery === 'undefined') { + throw 'bootstrap-datetimepicker requires jQuery to be loaded first'; + } + if (typeof moment === 'undefined') { + throw 'bootstrap-datetimepicker requires Moment.js to be loaded first'; + } + factory(jQuery, moment); + } +}(function ($, moment) { + 'use strict'; + if (!moment) { + throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first'); + } + + var dateTimePicker = function (element, options) { + var picker = {}, + date = moment(), + viewDate = date.clone(), + unset = true, + input, + component = false, + widget = false, + use24Hours, + minViewModeNumber = 0, + actualFormat, + parseFormats, + currentViewMode, + datePickerModes = [ + { + clsName: 'days', + navFnc: 'M', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'y', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'y', + navStep: 10 + } + ], + viewModes = ['days', 'months', 'years'], + verticalModes = ['top', 'bottom', 'auto'], + horizontalModes = ['left', 'right', 'auto'], + toolbarPlacements = ['default', 'top', 'bottom'], + keyMap = { + 'up': 38, + 38: 'up', + 'down': 40, + 40: 'down', + 'left': 37, + 37: 'left', + 'right': 39, + 39: 'right', + 'tab': 9, + 9: 'tab', + 'escape': 27, + 27: 'escape', + 'enter': 13, + 13: 'enter', + 'pageUp': 33, + 33: 'pageUp', + 'pageDown': 34, + 34: 'pageDown', + 'shift': 16, + 16: 'shift', + 'control': 17, + 17: 'control', + 'space': 32, + 32: 'space', + 't': 84, + 84: 't', + 'delete': 46, + 46: 'delete' + }, + keyState = {}, + + /******************************************************************************** + * + * Private functions + * + ********************************************************************************/ + isEnabled = function (granularity) { + if (typeof granularity !== 'string' || granularity.length > 1) { + throw new TypeError('isEnabled expects a single character string parameter'); + } + switch (granularity) { + case 'y': + return actualFormat.indexOf('Y') !== -1; + case 'M': + return actualFormat.indexOf('M') !== -1; + case 'd': + return actualFormat.toLowerCase().indexOf('d') !== -1; + case 'h': + case 'H': + return actualFormat.toLowerCase().indexOf('h') !== -1; + case 'm': + return actualFormat.indexOf('m') !== -1; + case 's': + return actualFormat.indexOf('s') !== -1; + default: + return false; + } + }, + + hasTime = function () { + return (isEnabled('h') || isEnabled('m') || isEnabled('s')); + }, + + hasDate = function () { + return (isEnabled('y') || isEnabled('M') || isEnabled('d')); + }, + + getDatePickerTemplate = function () { + var headTemplate = $('') + .append($('') + .append($('').addClass('prev').attr('data-action', 'previous') + .append($('').addClass(options.icons.previous)) + ) + .append($('').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5'))) + .append($('').addClass('next').attr('data-action', 'next') + .append($('').addClass(options.icons.next)) + ) + ), + contTemplate = $('') + .append($('') + .append($('').attr('colspan', (options.calendarWeeks ? '8' : '7'))) + ); + + return [ + $('
    ').addClass('datepicker-days') + .append($('').addClass('table-condensed') + .append(headTemplate) + .append($('')) + ), + $('
    ').addClass('datepicker-months') + .append($('
    ').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ), + $('
    ').addClass('datepicker-years') + .append($('
    ').addClass('table-condensed') + .append(headTemplate.clone()) + .append(contTemplate.clone()) + ) + ]; + }, + + getTimePickerMainTemplate = function () { + var topRow = $(''), + middleRow = $(''), + bottomRow = $(''); + + if (isEnabled('h')) { + topRow.append($('
    ') + .append($('').attr('href', '#').addClass('btn').attr('data-action', 'incrementHours') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-hour').attr('data-time-component', 'hours').attr('data-action', 'showHours'))); + bottomRow.append($('') + .append($('').attr('href', '#').addClass('btn').attr('data-action', 'decrementHours') + .append($('').addClass(options.icons.down)))); + } + if (isEnabled('m')) { + if (isEnabled('h')) { + topRow.append($('').addClass('separator')); + middleRow.append($('').addClass('separator').html(':')); + bottomRow.append($('').addClass('separator')); + } + topRow.append($('') + .append($('').attr('href', '#').addClass('btn').attr('data-action', 'incrementMinutes') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-minute').attr('data-time-component', 'minutes').attr('data-action', 'showMinutes'))); + bottomRow.append($('') + .append($('').attr('href', '#').addClass('btn').attr('data-action', 'decrementMinutes') + .append($('').addClass(options.icons.down)))); + } + if (isEnabled('s')) { + if (isEnabled('m')) { + topRow.append($('').addClass('separator')); + middleRow.append($('').addClass('separator').html(':')); + bottomRow.append($('').addClass('separator')); + } + topRow.append($('') + .append($('').attr('href', '#').addClass('btn').attr('data-action', 'incrementSeconds') + .append($('').addClass(options.icons.up)))); + middleRow.append($('') + .append($('').addClass('timepicker-second').attr('data-time-component', 'seconds').attr('data-action', 'showSeconds'))); + bottomRow.append($('') + .append($('').attr('href', '#').addClass('btn').attr('data-action', 'decrementSeconds') + .append($('').addClass(options.icons.down)))); + } + + if (!use24Hours) { + topRow.append($('').addClass('separator')); + middleRow.append($('') + .append($('').addClass('separator')); + } + + return $('
    ').addClass('timepicker-picker') + .append($('').addClass('table-condensed') + .append([topRow, middleRow, bottomRow])); + }, + + getTimePickerTemplate = function () { + var hoursView = $('
    ').addClass('timepicker-hours') + .append($('
    ').addClass('table-condensed')), + minutesView = $('
    ').addClass('timepicker-minutes') + .append($('
    ').addClass('table-condensed')), + secondsView = $('
    ').addClass('timepicker-seconds') + .append($('
    ').addClass('table-condensed')), + ret = [getTimePickerMainTemplate()]; + + if (isEnabled('h')) { + ret.push(hoursView); + } + if (isEnabled('m')) { + ret.push(minutesView); + } + if (isEnabled('s')) { + ret.push(secondsView); + } + + return ret; + }, + + getToolbar = function () { + var row = []; + if (options.showTodayButton) { + row.push($('
    ').append($('').attr('data-action', 'today').append($('').addClass(options.icons.today)))); + } + if (!options.sideBySide && hasDate() && hasTime()) { + row.push($('').append($('').attr('data-action', 'togglePicker').append($('').addClass(options.icons.time)))); + } + if (options.showClear) { + row.push($('').append($('').attr('data-action', 'clear').append($('').addClass(options.icons.clear)))); + } + return $('').addClass('table-condensed').append($('').append($('').append(row))); + }, + + getTemplate = function () { + var template = $('
    ').addClass('bootstrap-datetimepicker-widget dropdown-menu'), + dateView = $('
    ').addClass('datepicker').append(getDatePickerTemplate()), + timeView = $('
    ').addClass('timepicker').append(getTimePickerTemplate()), + content = $('
      ').addClass('list-unstyled'), + toolbar = $('
    • ').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar()); + + if (options.inline) { + template.removeClass('dropdown-menu'); + } + + if (use24Hours) { + template.addClass('usetwentyfour'); + } + if (options.sideBySide && hasDate() && hasTime()) { + template.addClass('timepicker-sbs'); + template.append( + $('
      ').addClass('row') + .append(dateView.addClass('col-sm-6')) + .append(timeView.addClass('col-sm-6')) + ); + template.append(toolbar); + return template; + } + + if (options.toolbarPlacement === 'top') { + content.append(toolbar); + } + if (hasDate()) { + content.append($('
    • ').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView)); + } + if (options.toolbarPlacement === 'default') { + content.append(toolbar); + } + if (hasTime()) { + content.append($('
    • ').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView)); + } + if (options.toolbarPlacement === 'bottom') { + content.append(toolbar); + } + return template.append(content); + }, + + dataToOptions = function () { + var eData, + dataOptions = {}; + + if (element.is('input')) { + eData = element.data(); + } else { + eData = element.find('input').data(); + } + + if (eData.dateOptions && eData.dateOptions instanceof Object) { + dataOptions = $.extend(true, dataOptions, eData.dateOptions); + } + + $.each(options, function (key) { + var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); + if (eData[attributeName] !== undefined) { + dataOptions[key] = eData[attributeName]; + } + }); + return dataOptions; + }, + + place = function () { + var position = (component || element).position(), + offset = (component || element).offset(), + vertical = options.widgetPositioning.vertical, + horizontal = options.widgetPositioning.horizontal, + parent; + + if (options.widgetParent) { + parent = options.widgetParent.append(widget); + } else if (element.is('input')) { + parent = element.parent().append(widget); + } else if (options.inline) { + parent = element.append(widget); + return; + } else { + parent = element; + element.children().first().after(widget); + } + + // Top and bottom logic + if (vertical === 'auto') { + if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && + widget.height() + element.outerHeight() < offset.top) { + vertical = 'top'; + } else { + vertical = 'bottom'; + } + } + + // Left and right logic + if (horizontal === 'auto') { + if (parent.width() < offset.left + widget.outerWidth() / 2 && + offset.left + widget.outerWidth() > $(window).width()) { + horizontal = 'right'; + } else { + horizontal = 'left'; + } + } + + if (vertical === 'top') { + widget.addClass('top').removeClass('bottom'); + } else { + widget.addClass('bottom').removeClass('top'); + } + + if (horizontal === 'right') { + widget.addClass('pull-right'); + } else { + widget.removeClass('pull-right'); + } + + // find the first parent element that has a relative css positioning + if (parent.css('position') !== 'relative') { + parent = parent.parents().filter(function () { + return $(this).css('position') === 'relative'; + }).first(); + } + + if (parent.length === 0) { + throw new Error('datetimepicker component should be placed within a relative positioned container'); + } + + widget.css({ + top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), + bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto', + left: horizontal === 'left' ? parent.css('padding-left') : 'auto', + right: horizontal === 'left' ? 'auto' : parent.width() - element.outerWidth() + }); + }, + + notifyEvent = function (e) { + if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { + return; + } + element.trigger(e); + }, + + showMode = function (dir) { + if (!widget) { + return; + } + if (dir) { + currentViewMode = Math.max(minViewModeNumber, Math.min(2, currentViewMode + dir)); + } + widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show(); + }, + + fillDow = function () { + var row = $('
    '), + currentDate = viewDate.clone().startOf('w'); + + if (options.calendarWeeks === true) { + row.append($(''); + if (options.calendarWeeks) { + row.append(''); + } + html.push(row); + } + clsName = ''; + if (currentDate.isBefore(viewDate, 'M')) { + clsName += ' old'; + } + if (currentDate.isAfter(viewDate, 'M')) { + clsName += ' new'; + } + if (currentDate.isSame(date, 'd') && !unset) { + clsName += ' active'; + } + if (!isValid(currentDate, 'd')) { + clsName += ' disabled'; + } + if (currentDate.isSame(moment(), 'd')) { + clsName += ' today'; + } + if (currentDate.day() === 0 || currentDate.day() === 6) { + clsName += ' weekend'; + } + row.append(''); + currentDate.add(1, 'd'); + } + + daysView.find('tbody').empty().append(html); + + updateMonths(); + + updateYears(); + }, + + fillHours = function () { + var table = widget.find('.timepicker-hours table'), + currentHour = viewDate.clone().startOf('d'), + html = [], + row = $(''); + + if (viewDate.hour() > 11 && !use24Hours) { + currentHour.hour(12); + } + while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) { + if (currentHour.hour() % 4 === 0) { + row = $(''); + html.push(row); + } + row.append(''); + currentHour.add(1, 'h'); + } + table.empty().append(html); + }, + + fillMinutes = function () { + var table = widget.find('.timepicker-minutes table'), + currentMinute = viewDate.clone().startOf('h'), + html = [], + row = $(''), + step = options.stepping === 1 ? 5 : options.stepping; + + while (viewDate.isSame(currentMinute, 'h')) { + if (currentMinute.minute() % (step * 4) === 0) { + row = $(''); + html.push(row); + } + row.append(''); + currentMinute.add(step, 'm'); + } + table.empty().append(html); + }, + + fillSeconds = function () { + var table = widget.find('.timepicker-seconds table'), + currentSecond = viewDate.clone().startOf('m'), + html = [], + row = $(''); + + while (viewDate.isSame(currentSecond, 'm')) { + if (currentSecond.second() % 20 === 0) { + row = $(''); + html.push(row); + } + row.append(''); + currentSecond.add(5, 's'); + } + + table.empty().append(html); + }, + + fillTime = function () { + var timeComponents = widget.find('.timepicker span[data-time-component]'); + if (!use24Hours) { + widget.find('.timepicker [data-action=togglePeriod]').text(date.format('A')); + } + timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh')); + timeComponents.filter('[data-time-component=minutes]').text(date.format('mm')); + timeComponents.filter('[data-time-component=seconds]').text(date.format('ss')); + + fillHours(); + fillMinutes(); + fillSeconds(); + }, + + update = function () { + if (!widget) { + return; + } + fillDate(); + fillTime(); + }, + + setValue = function (targetMoment) { + var oldDate = unset ? null : date; + + // case of calling setValue(null or false) + if (!targetMoment) { + unset = true; + input.val(''); + element.data('date', ''); + notifyEvent({ + type: 'dp.change', + date: null, + oldDate: oldDate + }); + update(); + return; + } + + targetMoment = targetMoment.clone().locale(options.locale); + + if (options.stepping !== 1) { + targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0); + } + + if (isValid(targetMoment)) { + date = targetMoment; + viewDate = date.clone(); + input.val(date.format(actualFormat)); + element.data('date', date.format(actualFormat)); + update(); + unset = false; + notifyEvent({ + type: 'dp.change', + date: date.clone(), + oldDate: oldDate + }); + } else { + input.val(unset ? '' : date.format(actualFormat)); + notifyEvent({ + type: 'dp.error', + date: targetMoment + }); + } + }, + + hide = function () { + var transitioning = false; + if (!widget) { + return picker; + } + // Ignore event if in the middle of a picker transition + widget.find('.collapse').each(function () { + var collapseData = $(this).data('collapse'); + if (collapseData && collapseData.transitioning) { + transitioning = true; + return false; + } + return true; + }); + if (transitioning) { + return picker; + } + if (component && component.hasClass('btn')) { + component.toggleClass('active'); + } + widget.hide(); + + $(window).off('resize', place); + widget.off('click', '[data-action]'); + widget.off('mousedown', false); + + widget.remove(); + widget = false; + + notifyEvent({ + type: 'dp.hide', + date: date.clone() + }); + return picker; + }, + + clear = function () { + setValue(null); + }, + + /******************************************************************************** + * + * Widget UI interaction functions + * + ********************************************************************************/ + actions = { + next: function () { + viewDate.add(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc); + fillDate(); + }, + + previous: function () { + viewDate.subtract(datePickerModes[currentViewMode].navStep, datePickerModes[currentViewMode].navFnc); + fillDate(); + }, + + pickerSwitch: function () { + showMode(1); + }, + + selectMonth: function (e) { + var month = $(e.target).closest('tbody').find('span').index($(e.target)); + viewDate.month(month); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year()).month(viewDate.month())); + hide(); + } else { + showMode(-1); + fillDate(); + } + }, + + selectYear: function (e) { + var year = parseInt($(e.target).text(), 10) || 0; + viewDate.year(year); + if (currentViewMode === minViewModeNumber) { + setValue(date.clone().year(viewDate.year())); + hide(); + } else { + showMode(-1); + fillDate(); + } + }, + + selectDay: function (e) { + var day = viewDate.clone(); + if ($(e.target).is('.old')) { + day.subtract(1, 'M'); + } + if ($(e.target).is('.new')) { + day.add(1, 'M'); + } + setValue(day.date(parseInt($(e.target).text(), 10))); + if (!hasTime() && !options.keepOpen) { + hide(); + } + }, + + incrementHours: function () { + setValue(date.clone().add(1, 'h')); + }, + + incrementMinutes: function () { + setValue(date.clone().add(options.stepping, 'm')); + }, + + incrementSeconds: function () { + setValue(date.clone().add(1, 's')); + }, + + decrementHours: function () { + setValue(date.clone().subtract(1, 'h')); + }, + + decrementMinutes: function () { + setValue(date.clone().subtract(options.stepping, 'm')); + }, + + decrementSeconds: function () { + setValue(date.clone().subtract(1, 's')); + }, + + togglePeriod: function () { + setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h')); + }, + + togglePicker: function (e) { + var $this = $(e.target), + $parent = $this.closest('ul'), + expanded = $parent.find('.in'), + closed = $parent.find('.collapse:not(.in)'), + collapseData; + + if (expanded && expanded.length) { + collapseData = expanded.data('collapse'); + if (collapseData && collapseData.transitioning) { + return; + } + if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it + expanded.collapse('hide'); + closed.collapse('show'); + } else { // otherwise just toggle in class on the two views + expanded.removeClass('in'); + closed.addClass('in'); + } + if ($this.is('span')) { + $this.toggleClass(options.icons.time + ' ' + options.icons.date); + } else { + $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); + } + + // NOTE: uncomment if toggled state will be restored in show() + //if (component) { + // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); + //} + } + }, + + showPicker: function () { + widget.find('.timepicker > div:not(.timepicker-picker)').hide(); + widget.find('.timepicker .timepicker-picker').show(); + }, + + showHours: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-hours').show(); + }, + + showMinutes: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-minutes').show(); + }, + + showSeconds: function () { + widget.find('.timepicker .timepicker-picker').hide(); + widget.find('.timepicker .timepicker-seconds').show(); + }, + + selectHour: function (e) { + var hour = parseInt($(e.target).text(), 10); + + if (!use24Hours) { + if (date.hours() >= 12) { + if (hour !== 12) { + hour += 12; + } + } else { + if (hour === 12) { + hour = 0; + } + } + } + setValue(date.clone().hours(hour)); + actions.showPicker.call(picker); + }, + + selectMinute: function (e) { + setValue(date.clone().minutes(parseInt($(e.target).text(), 10))); + actions.showPicker.call(picker); + }, + + selectSecond: function (e) { + setValue(date.clone().seconds(parseInt($(e.target).text(), 10))); + actions.showPicker.call(picker); + }, + + clear: clear, + + today: function () { + setValue(moment()); + } + }, + + doAction = function (e) { + if ($(e.currentTarget).is('.disabled')) { + return false; + } + actions[$(e.currentTarget).data('action')].apply(picker, arguments); + return false; + }, + + show = function () { + var currentMoment, + useCurrentGranularity = { + 'year': function (m) { + return m.month(0).date(1).hours(0).seconds(0).minutes(0); + }, + 'month': function (m) { + return m.date(1).hours(0).seconds(0).minutes(0); + }, + 'day': function (m) { + return m.hours(0).seconds(0).minutes(0); + }, + 'hour': function (m) { + return m.seconds(0).minutes(0); + }, + 'minute': function (m) { + return m.seconds(0); + } + }; + + if ((options.disallowReadOnly && (input.prop('disabled') || input.prop('readonly'))) || widget) { + return picker; + } + if (options.useCurrent && unset && (input.is('input') && input.val().trim().length === 0)) { + currentMoment = moment(); + if (typeof options.useCurrent === 'string') { + currentMoment = useCurrentGranularity[options.useCurrent](currentMoment); + } + setValue(currentMoment); + } + + widget = getTemplate(); + + fillDow(); + fillMonths(); + + widget.find('.timepicker-hours').hide(); + widget.find('.timepicker-minutes').hide(); + widget.find('.timepicker-seconds').hide(); + + update(); + showMode(); + + $(window).on('resize', place); + widget.on('click', '[data-action]', doAction); // this handles clicks on the widget + widget.on('mousedown', false); + + if (component && component.hasClass('btn')) { + component.toggleClass('active'); + } + widget.show(); + place(); + + if (!input.is(':focus')) { + input.focus(); + } + + notifyEvent({ + type: 'dp.show' + }); + return picker; + }, + + toggle = function () { + return (widget ? hide() : show()); + }, + + parseInputDate = function (inputDate) { + if (moment.isMoment(inputDate) || inputDate instanceof Date) { + inputDate = moment(inputDate); + } else { + inputDate = moment(inputDate, parseFormats, options.useStrict); + } + inputDate.locale(options.locale); + return inputDate; + }, + + keydown = function (e) { + //if (e.keyCode === 27 && widget) { // allow escape to hide picker + // hide(); + // return false; + //} + //if (e.keyCode === 40 && !widget) { // allow down to show picker + // show(); + // e.preventDefault(); + //} + //return true; + + var handler = null, + index, + index2, + pressedKeys = [], + pressedModifiers = {}, + currentKey = e.which, + keyBindKeys, + allModifiersPressed, + pressed = 'p'; + + keyState[currentKey] = pressed; + + for (index in keyState) { + if (keyState.hasOwnProperty(index) && keyState[index] === pressed) { + pressedKeys.push(index); + if (parseInt(index, 10) !== currentKey) { + pressedModifiers[index] = true; + } + } + } + + for (index in options.keyBinds) { + if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') { + keyBindKeys = index.split(' '); + if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) { + allModifiersPressed = true; + for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) { + if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) { + allModifiersPressed = false; + break; + } + } + if (allModifiersPressed) { + handler = options.keyBinds[index]; + break; + } + } + } + } + + if (handler) { + handler.call(picker, widget); + e.stopPropagation(); + e.preventDefault(); + } + }, + + keyup = function (e) { + keyState[e.which] = 'r'; + e.stopPropagation(); + e.preventDefault(); + }, + + change = function (e) { + var val = $(e.target).val().trim(), + parsedDate = val ? parseInputDate(val) : null; + setValue(parsedDate); + e.stopImmediatePropagation(); + return false; + }, + + attachDatePickerElementEvents = function () { + input.on({ + 'change': change, + 'blur': hide, + 'keydown': keydown, + 'keyup': keyup + }); + + if (element.is('input')) { + input.on({ + 'focus': show + }); + } else if (component) { + component.on('click', toggle); + component.on('mousedown', false); + } + }, + + detachDatePickerElementEvents = function () { + input.off({ + 'change': change, + 'blur': hide, + 'keydown': keydown, + 'keyup': keyup + }); + + if (element.is('input')) { + input.off({ + 'focus': show + }); + } else if (component) { + component.off('click', toggle); + component.off('mousedown', false); + } + }, + + indexGivenDates = function (givenDatesArray) { + // Store given enabledDates and disabledDates as keys. + // This way we can check their existence in O(1) time instead of looping through whole array. + // (for example: options.enabledDates['2014-02-27'] === true) + var givenDatesIndexed = {}; + $.each(givenDatesArray, function () { + var dDate = parseInputDate(this); + if (dDate.isValid()) { + givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; + } + }); + return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false; + }, + + initFormatting = function () { + var format = options.format || 'L LT'; + + actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) { + var newinput = moment().localeData().longDateFormat(formatInput) || formatInput; + return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740 + return moment().localeData().longDateFormat(formatInput2) || formatInput2; + }); + }); + + + parseFormats = options.extraFormats ? options.extraFormats.slice() : []; + if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) { + parseFormats.push(actualFormat); + } + + use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.indexOf('h') < 1); + + if (isEnabled('y')) { + minViewModeNumber = 2; + } + if (isEnabled('M')) { + minViewModeNumber = 1; + } + if (isEnabled('d')) { + minViewModeNumber = 0; + } + + currentViewMode = Math.max(minViewModeNumber, currentViewMode); + + if (!unset) { + setValue(date); + } + }; + + /******************************************************************************** + * + * Public API functions + * ===================== + * + * Important: Do not expose direct references to private objects or the options + * object to the outer world. Always return a clone when returning values or make + * a clone when setting a private variable. + * + ********************************************************************************/ + picker.destroy = function () { + hide(); + detachDatePickerElementEvents(); + element.removeData('DateTimePicker'); + element.removeData('date'); + }; + + picker.toggle = toggle; + + picker.show = show; + + picker.hide = hide; + + picker.disable = function () { + hide(); + if (component && component.hasClass('btn')) { + component.addClass('disabled'); + } + input.prop('disabled', true); + return picker; + }; + + picker.enable = function () { + if (component && component.hasClass('btn')) { + component.removeClass('disabled'); + } + input.prop('disabled', false); + return picker; + }; + + picker.disallowReadOnly = function (disallowReadOnly) { + if (arguments.length === 0) { + return options.disallowReadOnly; + } + if (typeof disallowReadOnly !== 'boolean') { + throw new TypeError('disallowReadOnly() expects a boolean parameter'); + } + options.disallowReadOnly = disallowReadOnly; + return picker; + }; + + picker.options = function (newOptions) { + if (arguments.length === 0) { + return $.extend(true, {}, options); + } + + if (!(newOptions instanceof Object)) { + throw new TypeError('options() options parameter should be an object'); + } + $.extend(true, options, newOptions); + $.each(options, function (key, value) { + if (picker[key] !== undefined) { + picker[key](value); + } else { + throw new TypeError('option ' + key + ' is not recognized!'); + } + }); + return picker; + }; + + picker.date = function (newDate) { + if (arguments.length === 0) { + if (unset) { + return null; + } + return date.clone(); + } + + if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { + throw new TypeError('date() parameter must be one of [null, string, moment or Date]'); + } + + setValue(newDate === null ? null : parseInputDate(newDate)); + return picker; + }; + + picker.format = function (newFormat) { + if (arguments.length === 0) { + return options.format; + } + + if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { + throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat); + } + + options.format = newFormat; + if (actualFormat) { + initFormatting(); // reinit formatting + } + return picker; + }; + + picker.dayViewHeaderFormat = function (newFormat) { + if (arguments.length === 0) { + return options.dayViewHeaderFormat; + } + + if (typeof newFormat !== 'string') { + throw new TypeError('dayViewHeaderFormat() expects a string parameter'); + } + + options.dayViewHeaderFormat = newFormat; + return picker; + }; + + picker.extraFormats = function (formats) { + if (arguments.length === 0) { + return options.extraFormats; + } + + if (formats !== false && !(formats instanceof Array)) { + throw new TypeError('extraFormats() expects an array or false parameter'); + } + + options.extraFormats = formats; + if (parseFormats) { + initFormatting(); // reinit formatting + } + return picker; + }; + + picker.disabledDates = function (dates) { + if (arguments.length === 0) { + return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates); + } + + if (!dates) { + options.disabledDates = false; + update(); + return picker; + } + if (!(dates instanceof Array)) { + throw new TypeError('disabledDates() expects an array parameter'); + } + options.disabledDates = indexGivenDates(dates); + options.enabledDates = false; + update(); + return picker; + }; + + picker.enabledDates = function (dates) { + if (arguments.length === 0) { + return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates); + } + + if (!dates) { + options.enabledDates = false; + update(); + return picker; + } + if (!(dates instanceof Array)) { + throw new TypeError('enabledDates() expects an array parameter'); + } + options.enabledDates = indexGivenDates(dates); + options.disabledDates = false; + update(); + return picker; + }; + + picker.daysOfWeekDisabled = function (daysOfWeekDisabled) { + if (arguments.length === 0) { + return options.daysOfWeekDisabled.splice(0); + } + + if (!(daysOfWeekDisabled instanceof Array)) { + throw new TypeError('daysOfWeekDisabled() expects an array parameter'); + } + options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) { + currentValue = parseInt(currentValue, 10); + if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) { + return previousValue; + } + if (previousValue.indexOf(currentValue) === -1) { + previousValue.push(currentValue); + } + return previousValue; + }, []).sort(); + update(); + return picker; + }; + + picker.maxDate = function (maxDate) { + if (arguments.length === 0) { + return options.maxDate ? options.maxDate.clone() : options.maxDate; + } + + if ((typeof maxDate === 'boolean') && maxDate === false) { + options.maxDate = false; + update(); + return picker; + } + + var parsedDate = parseInputDate(maxDate); + + if (!parsedDate.isValid()) { + throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate); + } + if (options.minDate && parsedDate.isBefore(options.minDate)) { + throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat)); + } + options.maxDate = parsedDate; + if (options.maxDate.isBefore(maxDate)) { + setValue(options.maxDate); + } + if (viewDate.isAfter(parsedDate)) { + viewDate = parsedDate; + } + update(); + return picker; + }; + + picker.minDate = function (minDate) { + if (arguments.length === 0) { + return options.minDate ? options.minDate.clone() : options.minDate; + } + + if ((typeof minDate === 'boolean') && minDate === false) { + options.minDate = false; + update(); + return picker; + } + + var parsedDate = parseInputDate(minDate); + + if (!parsedDate.isValid()) { + throw new TypeError('minDate() Could not parse date parameter: ' + minDate); + } + if (options.maxDate && parsedDate.isAfter(options.maxDate)) { + throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat)); + } + options.minDate = parsedDate; + if (options.minDate.isAfter(minDate)) { + setValue(options.minDate); + } + if (viewDate.isBefore(parsedDate)) { + viewDate = parsedDate; + } + update(); + return picker; + }; + + picker.defaultDate = function (defaultDate) { + if (arguments.length === 0) { + return options.defaultDate ? options.defaultDate.clone() : options.defaultDate; + } + if (!defaultDate) { + options.defaultDate = false; + return picker; + } + var parsedDate = parseInputDate(defaultDate); + if (!parsedDate.isValid()) { + throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate); + } + if (!isValid(parsedDate)) { + throw new TypeError('defaultDate() date passed is invalid according to component setup validations'); + } + + options.defaultDate = parsedDate; + + if (options.defaultDate && input.val().trim() === '') { + setValue(options.defaultDate); + } + return picker; + }; + + picker.locale = function (locale) { + if (arguments.length === 0) { + return options.locale; + } + + if (!moment.localeData(locale)) { + throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!'); + } + + options.locale = locale; + date.locale(options.locale); + viewDate.locale(options.locale); + + if (actualFormat) { + initFormatting(); // reinit formatting + } + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.stepping = function (stepping) { + if (arguments.length === 0) { + return options.stepping; + } + + stepping = parseInt(stepping, 10); + if (isNaN(stepping) || stepping < 1) { + stepping = 1; + } + options.stepping = stepping; + return picker; + }; + + picker.useCurrent = function (useCurrent) { + var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; + if (arguments.length === 0) { + return options.useCurrent; + } + + if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) { + throw new TypeError('useCurrent() expects a boolean or string parameter'); + } + if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) { + throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', ')); + } + options.useCurrent = useCurrent; + return picker; + }; + + picker.collapse = function (collapse) { + if (arguments.length === 0) { + return options.collapse; + } + + if (typeof collapse !== 'boolean') { + throw new TypeError('collapse() expects a boolean parameter'); + } + if (options.collapse === collapse) { + return picker; + } + options.collapse = collapse; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.icons = function (icons) { + if (arguments.length === 0) { + return $.extend({}, options.icons); + } + + if (!(icons instanceof Object)) { + throw new TypeError('icons() expects parameter to be an Object'); + } + $.extend(options.icons, icons); + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.useStrict = function (useStrict) { + if (arguments.length === 0) { + return options.useStrict; + } + + if (typeof useStrict !== 'boolean') { + throw new TypeError('useStrict() expects a boolean parameter'); + } + options.useStrict = useStrict; + return picker; + }; + + picker.sideBySide = function (sideBySide) { + if (arguments.length === 0) { + return options.sideBySide; + } + + if (typeof sideBySide !== 'boolean') { + throw new TypeError('sideBySide() expects a boolean parameter'); + } + options.sideBySide = sideBySide; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.viewMode = function (viewMode) { + if (arguments.length === 0) { + return options.viewMode; + } + + if (typeof viewMode !== 'string') { + throw new TypeError('viewMode() expects a string parameter'); + } + + if (viewModes.indexOf(viewMode) === -1) { + throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value'); + } + + options.viewMode = viewMode; + currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber); + + showMode(); + return picker; + }; + + picker.toolbarPlacement = function (toolbarPlacement) { + if (arguments.length === 0) { + return options.toolbarPlacement; + } + + if (typeof toolbarPlacement !== 'string') { + throw new TypeError('toolbarPlacement() expects a string parameter'); + } + if (toolbarPlacements.indexOf(toolbarPlacement) === -1) { + throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value'); + } + options.toolbarPlacement = toolbarPlacement; + + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.widgetPositioning = function (widgetPositioning) { + if (arguments.length === 0) { + return $.extend({}, options.widgetPositioning); + } + + if (({}).toString.call(widgetPositioning) !== '[object Object]') { + throw new TypeError('widgetPositioning() expects an object variable'); + } + if (widgetPositioning.horizontal) { + if (typeof widgetPositioning.horizontal !== 'string') { + throw new TypeError('widgetPositioning() horizontal variable must be a string'); + } + widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase(); + if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) { + throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')'); + } + options.widgetPositioning.horizontal = widgetPositioning.horizontal; + } + if (widgetPositioning.vertical) { + if (typeof widgetPositioning.vertical !== 'string') { + throw new TypeError('widgetPositioning() vertical variable must be a string'); + } + widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase(); + if (verticalModes.indexOf(widgetPositioning.vertical) === -1) { + throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')'); + } + options.widgetPositioning.vertical = widgetPositioning.vertical; + } + update(); + return picker; + }; + + picker.calendarWeeks = function (calendarWeeks) { + if (arguments.length === 0) { + return options.calendarWeeks; + } + + if (typeof calendarWeeks !== 'boolean') { + throw new TypeError('calendarWeeks() expects parameter to be a boolean value'); + } + + options.calendarWeeks = calendarWeeks; + update(); + return picker; + }; + + picker.showTodayButton = function (showTodayButton) { + if (arguments.length === 0) { + return options.showTodayButton; + } + + if (typeof showTodayButton !== 'boolean') { + throw new TypeError('showTodayButton() expects a boolean parameter'); + } + + options.showTodayButton = showTodayButton; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.showClear = function (showClear) { + if (arguments.length === 0) { + return options.showClear; + } + + if (typeof showClear !== 'boolean') { + throw new TypeError('showClear() expects a boolean parameter'); + } + + options.showClear = showClear; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.widgetParent = function (widgetParent) { + if (arguments.length === 0) { + return options.widgetParent; + } + + if (typeof widgetParent === 'string') { + widgetParent = $(widgetParent); + } + + if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) { + throw new TypeError('widgetParent() expects a string or a jQuery object parameter'); + } + + options.widgetParent = widgetParent; + if (widget) { + hide(); + show(); + } + return picker; + }; + + picker.keepOpen = function (keepOpen) { + if (arguments.length === 0) { + return options.keepOpen; + } + + if (typeof keepOpen !== 'boolean') { + throw new TypeError('keepOpen() expects a boolean parameter'); + } + + options.keepOpen = keepOpen; + return picker; + }; + + picker.inline = function (inline) { + if (arguments.length === 0) { + return options.inline; + } + + if (typeof inline !== 'boolean') { + throw new TypeError('inline() expects a boolean parameter'); + } + + options.inline = inline; + return picker; + }; + + picker.clear = function () { + clear(); + return picker; + }; + + picker.keyBinds = function (keyBinds) { + options.keyBinds = keyBinds; + return picker; + }; + + // initializing element and component attributes + if (element.is('input')) { + input = element; + } else { + input = element.find('.datepickerinput'); + if (input.size() === 0) { + input = element.find('input'); + } else if (!input.is('input')) { + throw new Error('CSS class "datepickerinput" cannot be applied to non input element'); + } + } + + if (element.hasClass('input-group')) { + // in case there is more then one 'input-group-addon' Issue #48 + if (element.find('.datepickerbutton').size() === 0) { + component = element.find('[class^="input-group-"]'); + } else { + component = element.find('.datepickerbutton'); + } + } + + if (!options.inline && !input.is('input')) { + throw new Error('Could not initialize DateTimePicker without an input element'); + } + + $.extend(true, options, dataToOptions()); + + picker.options(options); + + initFormatting(); + + attachDatePickerElementEvents(); + + if (input.prop('disabled')) { + picker.disable(); + } + + if (input.is('input') && input.val().trim().length !== 0) { + setValue(parseInputDate(input.val().trim())); + } else if (options.defaultDate) { + setValue(options.defaultDate); + } + if (options.inline) { + show(); + } + return picker; + }; + + /******************************************************************************** + * + * jQuery plugin constructor and defaults object + * + ********************************************************************************/ + + $.fn.datetimepicker = function (options) { + return this.each(function () { + var $this = $(this); + if (!$this.data('DateTimePicker')) { + // create a private copy of the defaults object + options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); + $this.data('DateTimePicker', dateTimePicker($this, options)); + } + }); + }; + + $.fn.datetimepicker.defaults = { + format: false, + dayViewHeaderFormat: 'MMMM YYYY', + extraFormats: false, + stepping: 1, + minDate: false, + maxDate: false, + useCurrent: true, + collapse: true, + locale: moment.locale(), + defaultDate: false, + disabledDates: false, + enabledDates: false, + icons: { + time: 'glyphicon glyphicon-time', + date: 'glyphicon glyphicon-calendar', + up: 'glyphicon glyphicon-chevron-up', + down: 'glyphicon glyphicon-chevron-down', + previous: 'glyphicon glyphicon-chevron-left', + next: 'glyphicon glyphicon-chevron-right', + today: 'glyphicon glyphicon-screenshot', + clear: 'glyphicon glyphicon-trash' + }, + useStrict: false, + sideBySide: false, + daysOfWeekDisabled: [], + calendarWeeks: false, + viewMode: 'days', + toolbarPlacement: 'default', + showTodayButton: false, + showClear: false, + widgetPositioning: { + horizontal: 'auto', + vertical: 'auto' + }, + widgetParent: null, + disallowReadOnly: true, + keepOpen: false, + inline: false, + keyBinds: { + up: function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().subtract(7, 'd')); + } else { + this.date(this.date().clone().add(1, 'm')); + } + }, + down: function (widget) { + if (!widget) { + this.show(); + } + else if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().add(7, 'd')); + } else { + this.date(this.date().clone().subtract(1, 'm')); + } + }, + 'control up': function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().subtract(1, 'y')); + } else { + this.date(this.date().clone().add(1, 'h')); + } + }, + 'control down': function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().add(1, 'y')); + } else { + this.date(this.date().clone().subtract(1, 'h')); + } + }, + left: function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().subtract(1, 'd')); + } + }, + right: function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().add(1, 'd')); + } + }, + pageUp: function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().subtract(1, 'M')); + } + }, + pageDown: function (widget) { + if (widget.find('.datepicker').is(':visible')) { + this.date(this.date().clone().add(1, 'M')); + } + }, + enter: function () { + this.hide(); + }, + escape: function () { + this.hide(); + }, + tab: function (widget) { + widget.find('.picker-switch a[data-action="togglePicker"]').click(); + }, + 'control space': function (widget) { + if (widget.find('.timepicker').is(':visible')) { + widget.find('.btn[data-action="togglePeriod"]').click(); + } + }, + t: function () { + this.date(moment()); + }, + 'delete': function () { + this.clear(); + } + + } + }; +})); diff --git a/app/assets/javascripts/jquery.mixitup.min.js b/vendor/assets/javascripts/jquery.mixitup.min.js similarity index 100% rename from app/assets/javascripts/jquery.mixitup.min.js rename to vendor/assets/javascripts/jquery.mixitup.min.js diff --git a/vendor/assets/javascripts/pickers.js b/vendor/assets/javascripts/pickers.js new file mode 100644 index 000000000..b1b57d1d6 --- /dev/null +++ b/vendor/assets/javascripts/pickers.js @@ -0,0 +1,47 @@ +var default_picker_options = { + icons: { + date: 'fa fa-calendar', + time: 'fa fa-clock-o', + up: 'fa fa-chevron-up', + down: 'fa fa-chevron-down', + previous: 'fa fa-chevron-left', + next: 'fa fa-chevron-right', + today: 'fa fa-crosshairs', + clear: 'fa fa-trash-o' + } + +} + +$(document).on('ready page:change', function() { + $('.datetimepicker').datetimepicker(default_picker_options); + + $('.timepicker').datetimepicker(default_picker_options); + + $('.datepicker').datetimepicker(default_picker_options); + + $('.datetimerange').each(function(){ + var $this = $(this) + var range1 = $($this.find('.input-group')[0]) + var range2 = $($this.find('.input-group')[1]) + + if(range1.data("DateTimePicker").date() != null) + range2.data("DateTimePicker").minDate(range1.data("DateTimePicker").date()); + + if(range2.data("DateTimePicker").date() != null) + range1.data("DateTimePicker").maxDate(range2.data("DateTimePicker").date()); + + range1.on("dp.change",function (e) { + if(e.date) + range2.data("DateTimePicker").minDate(e.date); + else + range2.data("DateTimePicker").minDate(false); + }); + + range2.on("dp.change",function (e) { + if(e.date) + range1.data("DateTimePicker").maxDate(e.date); + else + range1.data("DateTimePicker").maxDate(false); + }); + }) +}); diff --git a/vendor/assets/stylesheets/bootstrap-datetimepicker.css b/vendor/assets/stylesheets/bootstrap-datetimepicker.css new file mode 100644 index 000000000..f810a7dd4 --- /dev/null +++ b/vendor/assets/stylesheets/bootstrap-datetimepicker.css @@ -0,0 +1,366 @@ +/*! + * Datetimepicker for Bootstrap 3 +//! version : 4.3.5 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */ +.bootstrap-datetimepicker-widget { + list-style: none; +} +.bootstrap-datetimepicker-widget.dropdown-menu { + margin: 2px 0; + padding: 4px; + width: 19em; +} +@media (min-width: 768px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 992px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 1200px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +.bootstrap-datetimepicker-widget.dropdown-menu:before, +.bootstrap-datetimepicker-widget.dropdown-menu:after { + content: ''; + display: inline-block; + position: absolute; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #cccccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + top: -7px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + top: -6px; + left: 8px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #cccccc; + border-top-color: rgba(0, 0, 0, 0.2); + bottom: -7px; + left: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid white; + bottom: -6px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { + left: auto; + right: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { + left: auto; + right: 7px; +} +.bootstrap-datetimepicker-widget .list-unstyled { + margin: 0; +} +.bootstrap-datetimepicker-widget a[data-action] { + padding: 6px 0; +} +.bootstrap-datetimepicker-widget a[data-action]:active { + box-shadow: none; +} +.bootstrap-datetimepicker-widget .timepicker-hour, +.bootstrap-datetimepicker-widget .timepicker-minute, +.bootstrap-datetimepicker-widget .timepicker-second { + width: 54px; + font-weight: bold; + font-size: 1.2em; + margin: 0; +} +.bootstrap-datetimepicker-widget button[data-action] { + padding: 6px; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle AM/PM"; +} +.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Clear the picker"; +} +.bootstrap-datetimepicker-widget .btn[data-action="today"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Set the date to today"; +} +.bootstrap-datetimepicker-widget .picker-switch { + text-align: center; +} +.bootstrap-datetimepicker-widget .picker-switch::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle Date and Time Screens"; +} +.bootstrap-datetimepicker-widget .picker-switch td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; +} +.bootstrap-datetimepicker-widget .picker-switch td span { + line-height: 2.5; + height: 2.5em; + width: 100%; +} +.bootstrap-datetimepicker-widget table { + width: 100%; + margin: 0; +} +.bootstrap-datetimepicker-widget table td, +.bootstrap-datetimepicker-widget table th { + text-align: center; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table th { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table th.picker-switch { + width: 145px; +} +.bootstrap-datetimepicker-widget table th.disabled, +.bootstrap-datetimepicker-widget table th.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table th.prev::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Previous Month"; +} +.bootstrap-datetimepicker-widget table th.next::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Next Month"; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th { + cursor: pointer; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td { + height: 54px; + line-height: 54px; + width: 54px; +} +.bootstrap-datetimepicker-widget table td.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: #777777; +} +.bootstrap-datetimepicker-widget table td.day { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table td.day:hover, +.bootstrap-datetimepicker-widget table td.hour:hover, +.bootstrap-datetimepicker-widget table td.minute:hover, +.bootstrap-datetimepicker-widget table td.second:hover { + background: #eeeeee; + cursor: pointer; +} +.bootstrap-datetimepicker-widget table td.old, +.bootstrap-datetimepicker-widget table td.new { + color: #777777; +} +.bootstrap-datetimepicker-widget table td.today { + position: relative; +} +.bootstrap-datetimepicker-widget table td.today:before { + content: ''; + display: inline-block; + border: 0 0 7px 7px solid transparent; + border-bottom-color: #337ab7; + border-top-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: 4px; + right: 4px; +} +.bootstrap-datetimepicker-widget table td.active, +.bootstrap-datetimepicker-widget table td.active:hover { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td.active.today:before { + border-bottom-color: #fff; +} +.bootstrap-datetimepicker-widget table td.disabled, +.bootstrap-datetimepicker-widget table td.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table td span { + display: inline-block; + width: 54px; + height: 54px; + line-height: 54px; + margin: 2px 1.5px; + cursor: pointer; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table td span:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td span.active { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td span.old { + color: #777777; +} +.bootstrap-datetimepicker-widget table td span.disabled, +.bootstrap-datetimepicker-widget table td span.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget.usetwentyfour td.hour { + height: 27px; + line-height: 27px; +} +.input-group.date .input-group-addon { + cursor: pointer; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} diff --git a/vendor/assets/stylesheets/bootstrap-datetimepicker.min.css b/vendor/assets/stylesheets/bootstrap-datetimepicker.min.css new file mode 100644 index 000000000..f810a7dd4 --- /dev/null +++ b/vendor/assets/stylesheets/bootstrap-datetimepicker.min.css @@ -0,0 +1,366 @@ +/*! + * Datetimepicker for Bootstrap 3 +//! version : 4.3.5 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */ +.bootstrap-datetimepicker-widget { + list-style: none; +} +.bootstrap-datetimepicker-widget.dropdown-menu { + margin: 2px 0; + padding: 4px; + width: 19em; +} +@media (min-width: 768px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 992px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 1200px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +.bootstrap-datetimepicker-widget.dropdown-menu:before, +.bootstrap-datetimepicker-widget.dropdown-menu:after { + content: ''; + display: inline-block; + position: absolute; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #cccccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + top: -7px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + top: -6px; + left: 8px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #cccccc; + border-top-color: rgba(0, 0, 0, 0.2); + bottom: -7px; + left: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid white; + bottom: -6px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { + left: auto; + right: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { + left: auto; + right: 7px; +} +.bootstrap-datetimepicker-widget .list-unstyled { + margin: 0; +} +.bootstrap-datetimepicker-widget a[data-action] { + padding: 6px 0; +} +.bootstrap-datetimepicker-widget a[data-action]:active { + box-shadow: none; +} +.bootstrap-datetimepicker-widget .timepicker-hour, +.bootstrap-datetimepicker-widget .timepicker-minute, +.bootstrap-datetimepicker-widget .timepicker-second { + width: 54px; + font-weight: bold; + font-size: 1.2em; + margin: 0; +} +.bootstrap-datetimepicker-widget button[data-action] { + padding: 6px; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle AM/PM"; +} +.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Clear the picker"; +} +.bootstrap-datetimepicker-widget .btn[data-action="today"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Set the date to today"; +} +.bootstrap-datetimepicker-widget .picker-switch { + text-align: center; +} +.bootstrap-datetimepicker-widget .picker-switch::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle Date and Time Screens"; +} +.bootstrap-datetimepicker-widget .picker-switch td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; +} +.bootstrap-datetimepicker-widget .picker-switch td span { + line-height: 2.5; + height: 2.5em; + width: 100%; +} +.bootstrap-datetimepicker-widget table { + width: 100%; + margin: 0; +} +.bootstrap-datetimepicker-widget table td, +.bootstrap-datetimepicker-widget table th { + text-align: center; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table th { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table th.picker-switch { + width: 145px; +} +.bootstrap-datetimepicker-widget table th.disabled, +.bootstrap-datetimepicker-widget table th.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table th.prev::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Previous Month"; +} +.bootstrap-datetimepicker-widget table th.next::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Next Month"; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th { + cursor: pointer; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td { + height: 54px; + line-height: 54px; + width: 54px; +} +.bootstrap-datetimepicker-widget table td.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: #777777; +} +.bootstrap-datetimepicker-widget table td.day { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table td.day:hover, +.bootstrap-datetimepicker-widget table td.hour:hover, +.bootstrap-datetimepicker-widget table td.minute:hover, +.bootstrap-datetimepicker-widget table td.second:hover { + background: #eeeeee; + cursor: pointer; +} +.bootstrap-datetimepicker-widget table td.old, +.bootstrap-datetimepicker-widget table td.new { + color: #777777; +} +.bootstrap-datetimepicker-widget table td.today { + position: relative; +} +.bootstrap-datetimepicker-widget table td.today:before { + content: ''; + display: inline-block; + border: 0 0 7px 7px solid transparent; + border-bottom-color: #337ab7; + border-top-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: 4px; + right: 4px; +} +.bootstrap-datetimepicker-widget table td.active, +.bootstrap-datetimepicker-widget table td.active:hover { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td.active.today:before { + border-bottom-color: #fff; +} +.bootstrap-datetimepicker-widget table td.disabled, +.bootstrap-datetimepicker-widget table td.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table td span { + display: inline-block; + width: 54px; + height: 54px; + line-height: 54px; + margin: 2px 1.5px; + cursor: pointer; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table td span:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td span.active { + background-color: #337ab7; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td span.old { + color: #777777; +} +.bootstrap-datetimepicker-widget table td span.disabled, +.bootstrap-datetimepicker-widget table td span.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget.usetwentyfour td.hour { + height: 27px; + line-height: 27px; +} +.input-group.date .input-group-addon { + cursor: pointer; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} diff --git a/vendor/assets/stylesheets/bootstrap.css b/vendor/assets/stylesheets/bootstrap.css index 785084df9..a54d4ea2e 100644 --- a/vendor/assets/stylesheets/bootstrap.css +++ b/vendor/assets/stylesheets/bootstrap.css @@ -6,13 +6,15 @@ /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; } + body { - margin: 0; + margin: 0; } + article, aside, details, @@ -25,331 +27,403 @@ main, nav, section, summary { - display: block; + display: block; } + audio, canvas, progress, video { - display: inline-block; - vertical-align: baseline; + display: inline-block; + vertical-align: baseline; } + audio:not([controls]) { - display: none; - height: 0; + display: none; + height: 0; } + [hidden], template { - display: none; + display: none; } + a { - background: transparent; + background: transparent; } + a:active, a:hover { - outline: 0; + outline: 0; } + abbr[title] { - border-bottom: 1px dotted; + border-bottom: 1px dotted; } + b, strong { - font-weight: bold; + font-weight: bold; } + dfn { - font-style: italic; + font-style: italic; } + h1 { - margin: .67em 0; - font-size: 2em; + margin: .67em 0; + font-size: 2em; } + mark { - color: #000; - background: #ff0; + color: #000; + background: #ff0; } + small { - font-size: 80%; + font-size: 80%; } + sub, sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; } + sup { - top: -.5em; + top: -.5em; } + sub { - bottom: -.25em; + bottom: -.25em; } + img { - border: 0; + border: 0; } + svg:not(:root) { - overflow: hidden; + overflow: hidden; } + figure { - margin: 1em 40px; + margin: 1em 40px; } + hr { - height: 0; - -moz-box-sizing: content-box; - box-sizing: content-box; + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; } + pre { - overflow: auto; + overflow: auto; } + code, kbd, pre, samp { - font-family: monospace, monospace; - font-size: 1em; + font-family: monospace, monospace; + font-size: 1em; } + button, input, optgroup, select, textarea { - margin: 0; - font: inherit; - color: inherit; + margin: 0; + font: inherit; + color: inherit; } + button { - overflow: visible; + overflow: visible; } + button, select { - text-transform: none; + text-transform: none; } + button, html input[type="button"], input[type="reset"], input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; + -webkit-appearance: button; + cursor: pointer; } + button[disabled], html input[disabled] { - cursor: default; + cursor: default; } + button::-moz-focus-inner, input::-moz-focus-inner { - padding: 0; - border: 0; + padding: 0; + border: 0; } + input { - line-height: normal; + line-height: normal; } + input[type="checkbox"], input[type="radio"] { - box-sizing: border-box; - padding: 0; + box-sizing: border-box; + padding: 0; } + input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { - height: auto; + height: auto; } + input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; } + input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; + -webkit-appearance: none; } + fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; } + legend { - padding: 0; - border: 0; + padding: 0; + border: 0; } + textarea { - overflow: auto; + overflow: auto; } + optgroup { - font-weight: bold; + font-weight: bold; } + table { - border-spacing: 0; - border-collapse: collapse; + border-spacing: 0; + border-collapse: collapse; } + td, th { - padding: 0; + padding: 0; } + @media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - select { - background: #fff !important; - } - .navbar { - display: none; - } - .table td, - .table th { - background-color: #fff !important; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + select { + background: #fff !important; + } + + .navbar { + display: none; + } + + .table td, + .table th { + background-color: #fff !important; + } + + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + } + + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } } + * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + *:before, *:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + html { - font-size: 62.5%; + font-size: 62.5%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; } + input, button, select, textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; + font-family: inherit; + font-size: inherit; + line-height: inherit; } + a { - color: #428bca; - text-decoration: none; + color: #428bca; + text-decoration: none; } + a:hover, a:focus { - color: #2a6496; - text-decoration: underline; + color: #2a6496; + text-decoration: underline; } + a:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + figure { - margin: 0; + margin: 0; } + img { - vertical-align: middle; + vertical-align: middle; } + .img-responsive, .thumbnail > img, .thumbnail a > img, .carousel-inner > .item > img, .carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; + display: block; + max-width: 100%; + height: auto; } + .img-rounded { - border-radius: 6px; + border-radius: 6px; } + .img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; } + .img-circle { - border-radius: 50%; + border-radius: 50%; } + hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; } + .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; } + h1, h2, h3, @@ -362,11 +436,12 @@ h6, .h4, .h5, .h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; } + h1 small, h2 small, h3 small, @@ -391,19 +466,21 @@ h6 .small, .h4 .small, .h5 .small, .h6 .small { - font-weight: normal; - line-height: 1; - color: #999; + font-weight: normal; + line-height: 1; + color: #999; } + h1, .h1, h2, .h2, h3, .h3 { - margin-top: 20px; - margin-bottom: 10px; + margin-top: 20px; + margin-bottom: 10px; } + h1 small, .h1 small, h2 small, @@ -416,17 +493,19 @@ h2 .small, .h2 .small, h3 .small, .h3 .small { - font-size: 65%; + font-size: 65%; } + h4, .h4, h5, .h5, h6, .h6 { - margin-top: 10px; - margin-bottom: 10px; + margin-top: 10px; + margin-bottom: 10px; } + h4 small, .h4 small, h5 small, @@ -439,1049 +518,1346 @@ h5 .small, .h5 .small, h6 .small, .h6 .small { - font-size: 75%; + font-size: 75%; } + h1, .h1 { - font-size: 36px; + font-size: 36px; } + h2, .h2 { - font-size: 30px; + font-size: 30px; } + h3, .h3 { - font-size: 24px; + font-size: 24px; } + h4, .h4 { - font-size: 18px; + font-size: 18px; } + h5, .h5 { - font-size: 14px; + font-size: 14px; } + h6, .h6 { - font-size: 12px; + font-size: 12px; } + p { - margin: 0 0 10px; + margin: 0 0 10px; } + .lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 200; - line-height: 1.4; + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; } + @media (min-width: 768px) { - .lead { - font-size: 21px; - } + .lead { + font-size: 21px; + } } + small, .small { - font-size: 85%; + font-size: 85%; } + cite { - font-style: normal; + font-style: normal; } + .text-left { - text-align: left; + text-align: left; } + .text-right { - text-align: right; + text-align: right; } + .text-center { - text-align: center; + text-align: center; } + .text-justify { - text-align: justify; + text-align: justify; } + .text-muted { - color: #999; + color: #999; } + .text-primary { - color: #428bca; + color: #428bca; } + a.text-primary:hover { - color: #3071a9; + color: #3071a9; } + .text-success { - color: #3c763d; + color: #3c763d; } + a.text-success:hover { - color: #2b542c; + color: #2b542c; } + .text-info { - color: #31708f; + color: #31708f; } + a.text-info:hover { - color: #245269; + color: #245269; } + .text-warning { - color: #8a6d3b; + color: #8a6d3b; } + a.text-warning:hover { - color: #66512c; + color: #66512c; } + .text-danger { - color: #a94442; + color: #a94442; } + a.text-danger:hover { - color: #843534; + color: #843534; } + .bg-primary { - color: #fff; - background-color: #428bca; + color: #fff; + background-color: #428bca; } + a.bg-primary:hover { - background-color: #3071a9; + background-color: #3071a9; } + .bg-success { - background-color: #dff0d8; + background-color: #dff0d8; } + a.bg-success:hover { - background-color: #c1e2b3; + background-color: #c1e2b3; } + .bg-info { - background-color: #d9edf7; + background-color: #d9edf7; } + a.bg-info:hover { - background-color: #afd9ee; + background-color: #afd9ee; } + .bg-warning { - background-color: #fcf8e3; + background-color: #fcf8e3; } + a.bg-warning:hover { - background-color: #f7ecb5; + background-color: #f7ecb5; } + .bg-danger { - background-color: #f2dede; + background-color: #f2dede; } + a.bg-danger:hover { - background-color: #e4b9b9; + background-color: #e4b9b9; } + .page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; } + ul, ol { - margin-top: 0; - margin-bottom: 10px; + margin-top: 0; + margin-bottom: 10px; } + ul ul, ol ul, ul ol, ol ol { - margin-bottom: 0; + margin-bottom: 0; } + .list-unstyled { - padding-left: 0; - list-style: none; + padding-left: 0; + list-style: none; } + .list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; + padding-left: 0; + margin-left: -5px; + list-style: none; } + .list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; + display: inline-block; + padding-right: 5px; + padding-left: 5px; } + dl { - margin-top: 0; - margin-bottom: 20px; + margin-top: 0; + margin-bottom: 20px; } + dt, dd { - line-height: 1.42857143; + line-height: 1.42857143; } + dt { - font-weight: bold; + font-weight: bold; } + dd { - margin-left: 0; + margin-left: 0; } + @media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + + .dl-horizontal dd { + margin-left: 180px; + } } + abbr[title], abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999; + cursor: help; + border-bottom: 1px dotted #999; } + .initialism { - font-size: 90%; - text-transform: uppercase; + font-size: 90%; + text-transform: uppercase; } + blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; } + blockquote p:last-child, blockquote ul:last-child, blockquote ol:last-child { - margin-bottom: 0; + margin-bottom: 0; } + blockquote footer, blockquote small, blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #999; + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999; } + blockquote footer:before, blockquote small:before, blockquote .small:before { - content: '\2014 \00A0'; + content: '\2014 \00A0'; } + .blockquote-reverse, blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; } + .blockquote-reverse footer:before, blockquote.pull-right footer:before, .blockquote-reverse small:before, blockquote.pull-right small:before, .blockquote-reverse .small:before, blockquote.pull-right .small:before { - content: ''; + content: ''; } + .blockquote-reverse footer:after, blockquote.pull-right footer:after, .blockquote-reverse small:after, blockquote.pull-right small:after, .blockquote-reverse .small:after, blockquote.pull-right .small:after { - content: '\00A0 \2014'; + content: '\00A0 \2014'; } + blockquote:before, blockquote:after { - content: ""; + content: ""; } + address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; } + code, kbd, pre, samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; } + code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - white-space: nowrap; - background-color: #f9f2f4; - border-radius: 4px; + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + white-space: nowrap; + background-color: #f9f2f4; + border-radius: 4px; } + kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); } + pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; } + pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; } + .pre-scrollable { - max-height: 340px; - overflow-y: scroll; + max-height: 340px; + overflow-y: scroll; } + .container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; } + @media (min-width: 768px) { - .container { - width: 750px; - } + .container { + width: 750px; + } } + @media (min-width: 992px) { - .container { - width: 970px; - } + .container { + width: 970px; + } } + @media (min-width: 1200px) { - .container { - width: 1170px; - } + .container { + width: 1170px; + } } + .container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; } + .row { - margin-right: -15px; - margin-left: -15px; + margin-right: -15px; + margin-left: -15px; } + .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; } + .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; + float: left; } + .col-xs-12 { - width: 100%; + width: 100%; } + .col-xs-11 { - width: 91.66666667%; + width: 91.66666667%; } + .col-xs-10 { - width: 83.33333333%; + width: 83.33333333%; } + .col-xs-9 { - width: 75%; + width: 75%; } + .col-xs-8 { - width: 66.66666667%; + width: 66.66666667%; } + .col-xs-7 { - width: 58.33333333%; + width: 58.33333333%; } + .col-xs-6 { - width: 50%; + width: 50%; } + .col-xs-5 { - width: 41.66666667%; + width: 41.66666667%; } + .col-xs-4 { - width: 33.33333333%; + width: 33.33333333%; } + .col-xs-3 { - width: 25%; + width: 25%; } + .col-xs-2 { - width: 16.66666667%; + width: 16.66666667%; } + .col-xs-1 { - width: 8.33333333%; + width: 8.33333333%; } + .col-xs-pull-12 { - right: 100%; + right: 100%; } + .col-xs-pull-11 { - right: 91.66666667%; + right: 91.66666667%; } + .col-xs-pull-10 { - right: 83.33333333%; + right: 83.33333333%; } + .col-xs-pull-9 { - right: 75%; + right: 75%; } + .col-xs-pull-8 { - right: 66.66666667%; + right: 66.66666667%; } + .col-xs-pull-7 { - right: 58.33333333%; + right: 58.33333333%; } + .col-xs-pull-6 { - right: 50%; + right: 50%; } + .col-xs-pull-5 { - right: 41.66666667%; + right: 41.66666667%; } + .col-xs-pull-4 { - right: 33.33333333%; + right: 33.33333333%; } + .col-xs-pull-3 { - right: 25%; + right: 25%; } + .col-xs-pull-2 { - right: 16.66666667%; + right: 16.66666667%; } + .col-xs-pull-1 { - right: 8.33333333%; + right: 8.33333333%; } + .col-xs-pull-0 { - right: 0; + right: 0; } + .col-xs-push-12 { - left: 100%; + left: 100%; } + .col-xs-push-11 { - left: 91.66666667%; + left: 91.66666667%; } + .col-xs-push-10 { - left: 83.33333333%; + left: 83.33333333%; } + .col-xs-push-9 { - left: 75%; + left: 75%; } + .col-xs-push-8 { - left: 66.66666667%; + left: 66.66666667%; } + .col-xs-push-7 { - left: 58.33333333%; + left: 58.33333333%; } + .col-xs-push-6 { - left: 50%; + left: 50%; } + .col-xs-push-5 { - left: 41.66666667%; + left: 41.66666667%; } + .col-xs-push-4 { - left: 33.33333333%; + left: 33.33333333%; } + .col-xs-push-3 { - left: 25%; + left: 25%; } + .col-xs-push-2 { - left: 16.66666667%; + left: 16.66666667%; } + .col-xs-push-1 { - left: 8.33333333%; + left: 8.33333333%; } + .col-xs-push-0 { - left: 0; + left: 0; } + .col-xs-offset-12 { - margin-left: 100%; + margin-left: 100%; } + .col-xs-offset-11 { - margin-left: 91.66666667%; + margin-left: 91.66666667%; } + .col-xs-offset-10 { - margin-left: 83.33333333%; + margin-left: 83.33333333%; } + .col-xs-offset-9 { - margin-left: 75%; + margin-left: 75%; } + .col-xs-offset-8 { - margin-left: 66.66666667%; + margin-left: 66.66666667%; } + .col-xs-offset-7 { - margin-left: 58.33333333%; + margin-left: 58.33333333%; } + .col-xs-offset-6 { - margin-left: 50%; + margin-left: 50%; } + .col-xs-offset-5 { - margin-left: 41.66666667%; + margin-left: 41.66666667%; } + .col-xs-offset-4 { - margin-left: 33.33333333%; + margin-left: 33.33333333%; } + .col-xs-offset-3 { - margin-left: 25%; + margin-left: 25%; } + .col-xs-offset-2 { - margin-left: 16.66666667%; + margin-left: 16.66666667%; } + .col-xs-offset-1 { - margin-left: 8.33333333%; + margin-left: 8.33333333%; } + .col-xs-offset-0 { - margin-left: 0; + margin-left: 0; } + @media (min-width: 768px) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: 0; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: 0; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0; - } + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + + .col-sm-12 { + width: 100%; + } + + .col-sm-11 { + width: 91.66666667%; + } + + .col-sm-10 { + width: 83.33333333%; + } + + .col-sm-9 { + width: 75%; + } + + .col-sm-8 { + width: 66.66666667%; + } + + .col-sm-7 { + width: 58.33333333%; + } + + .col-sm-6 { + width: 50%; + } + + .col-sm-5 { + width: 41.66666667%; + } + + .col-sm-4 { + width: 33.33333333%; + } + + .col-sm-3 { + width: 25%; + } + + .col-sm-2 { + width: 16.66666667%; + } + + .col-sm-1 { + width: 8.33333333%; + } + + .col-sm-pull-12 { + right: 100%; + } + + .col-sm-pull-11 { + right: 91.66666667%; + } + + .col-sm-pull-10 { + right: 83.33333333%; + } + + .col-sm-pull-9 { + right: 75%; + } + + .col-sm-pull-8 { + right: 66.66666667%; + } + + .col-sm-pull-7 { + right: 58.33333333%; + } + + .col-sm-pull-6 { + right: 50%; + } + + .col-sm-pull-5 { + right: 41.66666667%; + } + + .col-sm-pull-4 { + right: 33.33333333%; + } + + .col-sm-pull-3 { + right: 25%; + } + + .col-sm-pull-2 { + right: 16.66666667%; + } + + .col-sm-pull-1 { + right: 8.33333333%; + } + + .col-sm-pull-0 { + right: 0; + } + + .col-sm-push-12 { + left: 100%; + } + + .col-sm-push-11 { + left: 91.66666667%; + } + + .col-sm-push-10 { + left: 83.33333333%; + } + + .col-sm-push-9 { + left: 75%; + } + + .col-sm-push-8 { + left: 66.66666667%; + } + + .col-sm-push-7 { + left: 58.33333333%; + } + + .col-sm-push-6 { + left: 50%; + } + + .col-sm-push-5 { + left: 41.66666667%; + } + + .col-sm-push-4 { + left: 33.33333333%; + } + + .col-sm-push-3 { + left: 25%; + } + + .col-sm-push-2 { + left: 16.66666667%; + } + + .col-sm-push-1 { + left: 8.33333333%; + } + + .col-sm-push-0 { + left: 0; + } + + .col-sm-offset-12 { + margin-left: 100%; + } + + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + + .col-sm-offset-9 { + margin-left: 75%; + } + + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + + .col-sm-offset-6 { + margin-left: 50%; + } + + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + + .col-sm-offset-3 { + margin-left: 25%; + } + + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + + .col-sm-offset-0 { + margin-left: 0; + } } + @media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: 0; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: 0; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0; - } + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + + .col-md-12 { + width: 100%; + } + + .col-md-11 { + width: 91.66666667%; + } + + .col-md-10 { + width: 83.33333333%; + } + + .col-md-9 { + width: 75%; + } + + .col-md-8 { + width: 66.66666667%; + } + + .col-md-7 { + width: 58.33333333%; + } + + .col-md-6 { + width: 50%; + } + + .col-md-5 { + width: 41.66666667%; + } + + .col-md-4 { + width: 33.33333333%; + } + + .col-md-3 { + width: 25%; + } + + .col-md-2 { + width: 16.66666667%; + } + + .col-md-1 { + width: 8.33333333%; + } + + .col-md-pull-12 { + right: 100%; + } + + .col-md-pull-11 { + right: 91.66666667%; + } + + .col-md-pull-10 { + right: 83.33333333%; + } + + .col-md-pull-9 { + right: 75%; + } + + .col-md-pull-8 { + right: 66.66666667%; + } + + .col-md-pull-7 { + right: 58.33333333%; + } + + .col-md-pull-6 { + right: 50%; + } + + .col-md-pull-5 { + right: 41.66666667%; + } + + .col-md-pull-4 { + right: 33.33333333%; + } + + .col-md-pull-3 { + right: 25%; + } + + .col-md-pull-2 { + right: 16.66666667%; + } + + .col-md-pull-1 { + right: 8.33333333%; + } + + .col-md-pull-0 { + right: 0; + } + + .col-md-push-12 { + left: 100%; + } + + .col-md-push-11 { + left: 91.66666667%; + } + + .col-md-push-10 { + left: 83.33333333%; + } + + .col-md-push-9 { + left: 75%; + } + + .col-md-push-8 { + left: 66.66666667%; + } + + .col-md-push-7 { + left: 58.33333333%; + } + + .col-md-push-6 { + left: 50%; + } + + .col-md-push-5 { + left: 41.66666667%; + } + + .col-md-push-4 { + left: 33.33333333%; + } + + .col-md-push-3 { + left: 25%; + } + + .col-md-push-2 { + left: 16.66666667%; + } + + .col-md-push-1 { + left: 8.33333333%; + } + + .col-md-push-0 { + left: 0; + } + + .col-md-offset-12 { + margin-left: 100%; + } + + .col-md-offset-11 { + margin-left: 91.66666667%; + } + + .col-md-offset-10 { + margin-left: 83.33333333%; + } + + .col-md-offset-9 { + margin-left: 75%; + } + + .col-md-offset-8 { + margin-left: 66.66666667%; + } + + .col-md-offset-7 { + margin-left: 58.33333333%; + } + + .col-md-offset-6 { + margin-left: 50%; + } + + .col-md-offset-5 { + margin-left: 41.66666667%; + } + + .col-md-offset-4 { + margin-left: 33.33333333%; + } + + .col-md-offset-3 { + margin-left: 25%; + } + + .col-md-offset-2 { + margin-left: 16.66666667%; + } + + .col-md-offset-1 { + margin-left: 8.33333333%; + } + + .col-md-offset-0 { + margin-left: 0; + } } + @media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: 0; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: 0; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + + .col-lg-12 { + width: 100%; + } + + .col-lg-11 { + width: 91.66666667%; + } + + .col-lg-10 { + width: 83.33333333%; + } + + .col-lg-9 { + width: 75%; + } + + .col-lg-8 { + width: 66.66666667%; + } + + .col-lg-7 { + width: 58.33333333%; + } + + .col-lg-6 { + width: 50%; + } + + .col-lg-5 { + width: 41.66666667%; + } + + .col-lg-4 { + width: 33.33333333%; + } + + .col-lg-3 { + width: 25%; + } + + .col-lg-2 { + width: 16.66666667%; + } + + .col-lg-1 { + width: 8.33333333%; + } + + .col-lg-pull-12 { + right: 100%; + } + + .col-lg-pull-11 { + right: 91.66666667%; + } + + .col-lg-pull-10 { + right: 83.33333333%; + } + + .col-lg-pull-9 { + right: 75%; + } + + .col-lg-pull-8 { + right: 66.66666667%; + } + + .col-lg-pull-7 { + right: 58.33333333%; + } + + .col-lg-pull-6 { + right: 50%; + } + + .col-lg-pull-5 { + right: 41.66666667%; + } + + .col-lg-pull-4 { + right: 33.33333333%; + } + + .col-lg-pull-3 { + right: 25%; + } + + .col-lg-pull-2 { + right: 16.66666667%; + } + + .col-lg-pull-1 { + right: 8.33333333%; + } + + .col-lg-pull-0 { + right: 0; + } + + .col-lg-push-12 { + left: 100%; + } + + .col-lg-push-11 { + left: 91.66666667%; + } + + .col-lg-push-10 { + left: 83.33333333%; + } + + .col-lg-push-9 { + left: 75%; + } + + .col-lg-push-8 { + left: 66.66666667%; + } + + .col-lg-push-7 { + left: 58.33333333%; + } + + .col-lg-push-6 { + left: 50%; + } + + .col-lg-push-5 { + left: 41.66666667%; + } + + .col-lg-push-4 { + left: 33.33333333%; + } + + .col-lg-push-3 { + left: 25%; + } + + .col-lg-push-2 { + left: 16.66666667%; + } + + .col-lg-push-1 { + left: 8.33333333%; + } + + .col-lg-push-0 { + left: 0; + } + + .col-lg-offset-12 { + margin-left: 100%; + } + + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + + .col-lg-offset-9 { + margin-left: 75%; + } + + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + + .col-lg-offset-6 { + margin-left: 50%; + } + + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + + .col-lg-offset-3 { + margin-left: 25%; + } + + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + + .col-lg-offset-0 { + margin-left: 0; + } } + table { - max-width: 100%; - background-color: transparent; + max-width: 100%; + background-color: transparent; } + th { - text-align: left; + text-align: left; } + .table { - width: 100%; - margin-bottom: 20px; + width: 100%; + margin-bottom: 20px; } + .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; } + .table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; + vertical-align: bottom; + border-bottom: 2px solid #ddd; } + .table > caption + thead > tr:first-child > th, .table > colgroup + thead > tr:first-child > th, .table > thead:first-child > tr:first-child > th, .table > caption + thead > tr:first-child > td, .table > colgroup + thead > tr:first-child > td, .table > thead:first-child > tr:first-child > td { - border-top: 0; + border-top: 0; } + .table > tbody + tbody { - border-top: 2px solid #ddd; + border-top: 2px solid #ddd; } + .table .table { - background-color: #fff; + background-color: #fff; } + .table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { - padding: 5px; + padding: 5px; } + .table-bordered { - border: 1px solid #ddd; + border: 1px solid #ddd; } + .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { - border: 1px solid #ddd; + border: 1px solid #ddd; } + .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { - border-bottom-width: 2px; + border-bottom-width: 2px; } + .table-striped > tbody > tr:nth-child(odd) > td, .table-striped > tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; + background-color: #f9f9f9; } + .table-hover > tbody > tr:hover > td, .table-hover > tbody > tr:hover > th { - background-color: #f5f5f5; + background-color: #f5f5f5; } + table col[class*="col-"] { - position: static; - display: table-column; - float: none; + position: static; + display: table-column; + float: none; } + table td[class*="col-"], table th[class*="col-"] { - position: static; - display: table-cell; - float: none; + position: static; + display: table-cell; + float: none; } + .table > thead > tr > td.active, .table > tbody > tr > td.active, .table > tfoot > tr > td.active, @@ -1494,14 +1870,16 @@ table th[class*="col-"] { .table > thead > tr.active > th, .table > tbody > tr.active > th, .table > tfoot > tr.active > th { - background-color: #f5f5f5; + background-color: #f5f5f5; } + .table-hover > tbody > tr > td.active:hover, .table-hover > tbody > tr > th.active:hover, .table-hover > tbody > tr.active:hover > td, .table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; + background-color: #e8e8e8; } + .table > thead > tr > td.success, .table > tbody > tr > td.success, .table > tfoot > tr > td.success, @@ -1514,14 +1892,16 @@ table th[class*="col-"] { .table > thead > tr.success > th, .table > tbody > tr.success > th, .table > tfoot > tr.success > th { - background-color: #dff0d8; + background-color: #dff0d8; } + .table-hover > tbody > tr > td.success:hover, .table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td, .table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; + background-color: #d0e9c6; } + .table > thead > tr > td.info, .table > tbody > tr > td.info, .table > tfoot > tr > td.info, @@ -1534,14 +1914,16 @@ table th[class*="col-"] { .table > thead > tr.info > th, .table > tbody > tr.info > th, .table > tfoot > tr.info > th { - background-color: #d9edf7; + background-color: #d9edf7; } + .table-hover > tbody > tr > td.info:hover, .table-hover > tbody > tr > th.info:hover, .table-hover > tbody > tr.info:hover > td, .table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; + background-color: #c4e3f3; } + .table > thead > tr > td.warning, .table > tbody > tr > td.warning, .table > tfoot > tr > td.warning, @@ -1554,14 +1936,16 @@ table th[class*="col-"] { .table > thead > tr.warning > th, .table > tbody > tr.warning > th, .table > tfoot > tr.warning > th { - background-color: #fcf8e3; + background-color: #fcf8e3; } + .table-hover > tbody > tr > td.warning:hover, .table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td, .table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; + background-color: #faf2cc; } + .table > thead > tr > td.danger, .table > tbody > tr > td.danger, .table > tfoot > tr > td.danger, @@ -1574,211 +1958,246 @@ table th[class*="col-"] { .table > thead > tr.danger > th, .table > tbody > tr.danger > th, .table > tfoot > tr.danger > th { - background-color: #f2dede; + background-color: #f2dede; } + .table-hover > tbody > tr > td.danger:hover, .table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td, .table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; + background-color: #ebcccc; } + @media (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-x: scroll; - overflow-y: hidden; - -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-x: scroll; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + + .table-responsive > .table { + margin-bottom: 0; + } + + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + + .table-responsive > .table-bordered { + border: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } } + fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; + min-width: 0; + padding: 0; + margin: 0; + border: 0; } + legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5; + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; } + label { - display: inline-block; - margin-bottom: 5px; - font-weight: bold; + display: inline-block; + margin-bottom: 5px; + font-weight: bold; } + input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + input[type="radio"], input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - /* IE8-9 */ - line-height: normal; + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; } + input[type="file"] { - display: block; + display: block; } + input[type="range"] { - display: block; - width: 100%; + display: block; + width: 100%; } + select[multiple], select[size] { - height: auto; + height: auto; } + input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; } + .form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } + .form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); } + .form-control::-moz-placeholder { - color: #999; - opacity: 1; + color: #999; + opacity: 1; } + .form-control:-ms-input-placeholder { - color: #999; + color: #999; } + .form-control::-webkit-input-placeholder { - color: #999; + color: #999; } + .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { - cursor: not-allowed; - background-color: #eee; - opacity: 1; + cursor: not-allowed; + background-color: #eee; + opacity: 1; } + textarea.form-control { - height: auto; + height: auto; } + input[type="search"] { - -webkit-appearance: none; + -webkit-appearance: none; } + input[type="date"] { - line-height: 34px; + line-height: 34px; } + .form-group { - margin-bottom: 15px; + margin-bottom: 15px; } + .radio, .checkbox { - display: block; - min-height: 20px; - padding-left: 20px; - margin-top: 10px; - margin-bottom: 10px; + display: block; + min-height: 20px; + padding-left: 20px; + margin-top: 10px; + margin-bottom: 10px; } + .radio label, .checkbox label { - display: inline; - font-weight: normal; - cursor: pointer; + display: inline; + font-weight: normal; + cursor: pointer; } + .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { - float: left; - margin-left: -20px; + float: left; + margin-left: -20px; } + .radio + .radio, .checkbox + .checkbox { - margin-top: -5px; + margin-top: -5px; } + .radio-inline, .checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; } + .radio-inline + .radio-inline, .checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; + margin-top: 0; + margin-left: 10px; } + input[type="radio"][disabled], input[type="checkbox"][disabled], .radio[disabled], @@ -1791,272 +2210,320 @@ fieldset[disabled] .radio, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox, fieldset[disabled] .checkbox-inline { - cursor: not-allowed; + cursor: not-allowed; } + .input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + select.input-sm { - height: 30px; - line-height: 30px; + height: 30px; + line-height: 30px; } + textarea.input-sm, select[multiple].input-sm { - height: auto; + height: auto; } + .input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; } + select.input-lg { - height: 46px; - line-height: 46px; + height: 46px; + line-height: 46px; } + textarea.input-lg, select[multiple].input-lg { - height: auto; + height: auto; } + .has-feedback { - position: relative; + position: relative; } + .has-feedback .form-control { - padding-right: 42.5px; + padding-right: 42.5px; } + .has-feedback .form-control-feedback { - position: absolute; - top: 25px; - right: 0; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; + position: absolute; + top: 25px; + right: 0; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; } + .has-success .help-block, .has-success .control-label, .has-success .radio, .has-success .checkbox, .has-success .radio-inline, .has-success .checkbox-inline { - color: #3c763d; + color: #3c763d; } + .has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } + .has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; } + .has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; } + .has-success .form-control-feedback { - color: #3c763d; + color: #3c763d; } + .has-warning .help-block, .has-warning .control-label, .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, .has-warning .checkbox-inline { - color: #8a6d3b; + color: #8a6d3b; } + .has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } + .has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; } + .has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; } + .has-warning .form-control-feedback { - color: #8a6d3b; + color: #8a6d3b; } + .has-error .help-block, .has-error .control-label, .has-error .radio, .has-error .checkbox, .has-error .radio-inline, .has-error .checkbox-inline { - color: #a94442; + color: #a94442; } + .has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } + .has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; } + .has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; + color: #a94442; + background-color: #f2dede; + border-color: #a94442; } + .has-error .form-control-feedback { - color: #a94442; + color: #a94442; } + .form-control-static { - margin-bottom: 0; + margin-bottom: 0; } + .help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; } + @media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .form-inline .input-group > .form-control { + width: 100%; + } + + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + + .form-inline .has-feedback .form-control-feedback { + top: 0; + } } + .form-horizontal .control-label, .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; } + .form-horizontal .radio, .form-horizontal .checkbox { - min-height: 27px; + min-height: 27px; } + .form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; + margin-right: -15px; + margin-left: -15px; } + .form-horizontal .form-control-static { - padding-top: 7px; + padding-top: 7px; } + @media (min-width: 768px) { - .form-horizontal .control-label { - text-align: right; - } + .form-horizontal .control-label { + text-align: right; + } } + .form-horizontal .has-feedback .form-control-feedback { - top: 0; - right: 15px; + top: 0; + right: 15px; } + .btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; } + .btn:focus, .btn:active:focus, .btn.active:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + .btn:hover, .btn:focus { - color: #333; - text-decoration: none; + color: #333; + text-decoration: none; } + .btn:active, .btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } + .btn.disabled, .btn[disabled], fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; } + .btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; + color: #333; + background-color: #fff; + border-color: #ccc; } + .btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { - color: #333; - background-color: #ebebeb; - border-color: #adadad; + color: #333; + background-color: #ebebeb; + border-color: #adadad; } + .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { - background-image: none; + background-image: none; } + .btn-default.disabled, .btn-default[disabled], fieldset[disabled] .btn-default, @@ -2072,32 +2539,37 @@ fieldset[disabled] .btn-default:active, .btn-default.disabled.active, .btn-default[disabled].active, fieldset[disabled] .btn-default.active { - background-color: #fff; - border-color: #ccc; + background-color: #fff; + border-color: #ccc; } + .btn-default .badge { - color: #fff; - background-color: #333; + color: #fff; + background-color: #333; } + .btn-primary { - color: #fff; - background-color: #428bca; - border-color: #357ebd; + color: #fff; + background-color: #428bca; + border-color: #357ebd; } + .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { - color: #fff; - background-color: #3276b1; - border-color: #285e8e; + color: #fff; + background-color: #3276b1; + border-color: #285e8e; } + .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { - background-image: none; + background-image: none; } + .btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, @@ -2113,32 +2585,37 @@ fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { - background-color: #428bca; - border-color: #357ebd; + background-color: #428bca; + border-color: #357ebd; } + .btn-primary .badge { - color: #428bca; - background-color: #fff; + color: #428bca; + background-color: #fff; } + .btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; } + .btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { - color: #fff; - background-color: #47a447; - border-color: #398439; + color: #fff; + background-color: #47a447; + border-color: #398439; } + .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { - background-image: none; + background-image: none; } + .btn-success.disabled, .btn-success[disabled], fieldset[disabled] .btn-success, @@ -2154,32 +2631,37 @@ fieldset[disabled] .btn-success:active, .btn-success.disabled.active, .btn-success[disabled].active, fieldset[disabled] .btn-success.active { - background-color: #5cb85c; - border-color: #4cae4c; + background-color: #5cb85c; + border-color: #4cae4c; } + .btn-success .badge { - color: #5cb85c; - background-color: #fff; + color: #5cb85c; + background-color: #fff; } + .btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; } + .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { - color: #fff; - background-color: #39b3d7; - border-color: #269abc; + color: #fff; + background-color: #39b3d7; + border-color: #269abc; } + .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { - background-image: none; + background-image: none; } + .btn-info.disabled, .btn-info[disabled], fieldset[disabled] .btn-info, @@ -2195,32 +2677,37 @@ fieldset[disabled] .btn-info:active, .btn-info.disabled.active, .btn-info[disabled].active, fieldset[disabled] .btn-info.active { - background-color: #5bc0de; - border-color: #46b8da; + background-color: #5bc0de; + border-color: #46b8da; } + .btn-info .badge { - color: #5bc0de; - background-color: #fff; + color: #5bc0de; + background-color: #fff; } + .btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; } + .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ed9c28; - border-color: #d58512; + color: #fff; + background-color: #ed9c28; + border-color: #d58512; } + .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { - background-image: none; + background-image: none; } + .btn-warning.disabled, .btn-warning[disabled], fieldset[disabled] .btn-warning, @@ -2236,32 +2723,37 @@ fieldset[disabled] .btn-warning:active, .btn-warning.disabled.active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning.active { - background-color: #f0ad4e; - border-color: #eea236; + background-color: #f0ad4e; + border-color: #eea236; } + .btn-warning .badge { - color: #f0ad4e; - background-color: #fff; + color: #f0ad4e; + background-color: #fff; } + .btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; } + .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { - color: #fff; - background-color: #d2322d; - border-color: #ac2925; + color: #fff; + background-color: #d2322d; + border-color: #ac2925; } + .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { - background-image: none; + background-image: none; } + .btn-danger.disabled, .btn-danger[disabled], fieldset[disabled] .btn-danger, @@ -2277,868 +2769,1112 @@ fieldset[disabled] .btn-danger:active, .btn-danger.disabled.active, .btn-danger[disabled].active, fieldset[disabled] .btn-danger.active { - background-color: #d9534f; - border-color: #d43f3a; + background-color: #d9534f; + border-color: #d43f3a; } + .btn-danger .badge { - color: #d9534f; - background-color: #fff; + color: #d9534f; + background-color: #fff; } + .btn-link { - font-weight: normal; - color: #428bca; - cursor: pointer; - border-radius: 0; + font-weight: normal; + color: #428bca; + cursor: pointer; + border-radius: 0; } + .btn-link, .btn-link:active, .btn-link[disabled], fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; } + .btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { - border-color: transparent; + border-color: transparent; } + .btn-link:hover, .btn-link:focus { - color: #2a6496; - text-decoration: underline; - background-color: transparent; + color: #2a6496; + text-decoration: underline; + background-color: transparent; } + .btn-link[disabled]:hover, fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { - color: #999; - text-decoration: none; + color: #999; + text-decoration: none; } + .btn-lg, .btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; } + .btn-sm, .btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + .btn-xs, .btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + .btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; } + .btn-block + .btn-block { - margin-top: 5px; + margin-top: 5px; } + input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { - width: 100%; + width: 100%; } + .fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - transition: opacity .15s linear; + opacity: 0; + -webkit-transition: opacity .15s linear; + transition: opacity .15s linear; } + .fade.in { - opacity: 1; + opacity: 1; } + .collapse { - display: none; + display: none; } + .collapse.in { - display: block; + display: block; } + .collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height .35s ease; - transition: height .35s ease; + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height .35s ease; + transition: height .35s ease; } + @font-face { - font-family: 'Glyphicons Halflings'; + font-family: 'Glyphicons Halflings'; - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); } + .glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + .glyphicon-asterisk:before { - content: "\2a"; + content: "\2a"; } + .glyphicon-plus:before { - content: "\2b"; + content: "\2b"; } + .glyphicon-euro:before { - content: "\20ac"; + content: "\20ac"; } + .glyphicon-minus:before { - content: "\2212"; + content: "\2212"; } + .glyphicon-cloud:before { - content: "\2601"; + content: "\2601"; } + .glyphicon-envelope:before { - content: "\2709"; + content: "\2709"; } + .glyphicon-pencil:before { - content: "\270f"; + content: "\270f"; } + .glyphicon-glass:before { - content: "\e001"; + content: "\e001"; } + .glyphicon-music:before { - content: "\e002"; + content: "\e002"; } + .glyphicon-search:before { - content: "\e003"; + content: "\e003"; } + .glyphicon-heart:before { - content: "\e005"; + content: "\e005"; } + .glyphicon-star:before { - content: "\e006"; + content: "\e006"; } + .glyphicon-star-empty:before { - content: "\e007"; + content: "\e007"; } + .glyphicon-user:before { - content: "\e008"; + content: "\e008"; } + .glyphicon-film:before { - content: "\e009"; + content: "\e009"; } + .glyphicon-th-large:before { - content: "\e010"; + content: "\e010"; } + .glyphicon-th:before { - content: "\e011"; + content: "\e011"; } + .glyphicon-th-list:before { - content: "\e012"; + content: "\e012"; } + .glyphicon-ok:before { - content: "\e013"; + content: "\e013"; } + .glyphicon-remove:before { - content: "\e014"; + content: "\e014"; } + .glyphicon-zoom-in:before { - content: "\e015"; + content: "\e015"; } + .glyphicon-zoom-out:before { - content: "\e016"; + content: "\e016"; } + .glyphicon-off:before { - content: "\e017"; + content: "\e017"; } + .glyphicon-signal:before { - content: "\e018"; + content: "\e018"; } + .glyphicon-cog:before { - content: "\e019"; + content: "\e019"; } + .glyphicon-trash:before { - content: "\e020"; + content: "\e020"; } + .glyphicon-home:before { - content: "\e021"; + content: "\e021"; } + .glyphicon-file:before { - content: "\e022"; + content: "\e022"; } + .glyphicon-time:before { - content: "\e023"; + content: "\e023"; } + .glyphicon-road:before { - content: "\e024"; + content: "\e024"; } + .glyphicon-download-alt:before { - content: "\e025"; + content: "\e025"; } + .glyphicon-download:before { - content: "\e026"; + content: "\e026"; } + .glyphicon-upload:before { - content: "\e027"; + content: "\e027"; } + .glyphicon-inbox:before { - content: "\e028"; + content: "\e028"; } + .glyphicon-play-circle:before { - content: "\e029"; + content: "\e029"; } + .glyphicon-repeat:before { - content: "\e030"; + content: "\e030"; } + .glyphicon-refresh:before { - content: "\e031"; + content: "\e031"; } + .glyphicon-list-alt:before { - content: "\e032"; + content: "\e032"; } + .glyphicon-lock:before { - content: "\e033"; + content: "\e033"; } + .glyphicon-flag:before { - content: "\e034"; + content: "\e034"; } + .glyphicon-headphones:before { - content: "\e035"; + content: "\e035"; } + .glyphicon-volume-off:before { - content: "\e036"; + content: "\e036"; } + .glyphicon-volume-down:before { - content: "\e037"; + content: "\e037"; } + .glyphicon-volume-up:before { - content: "\e038"; + content: "\e038"; } + .glyphicon-qrcode:before { - content: "\e039"; + content: "\e039"; } + .glyphicon-barcode:before { - content: "\e040"; + content: "\e040"; } + .glyphicon-tag:before { - content: "\e041"; + content: "\e041"; } + .glyphicon-tags:before { - content: "\e042"; + content: "\e042"; } + .glyphicon-book:before { - content: "\e043"; + content: "\e043"; } + .glyphicon-bookmark:before { - content: "\e044"; + content: "\e044"; } + .glyphicon-print:before { - content: "\e045"; + content: "\e045"; } + .glyphicon-camera:before { - content: "\e046"; + content: "\e046"; } + .glyphicon-font:before { - content: "\e047"; + content: "\e047"; } + .glyphicon-bold:before { - content: "\e048"; + content: "\e048"; } + .glyphicon-italic:before { - content: "\e049"; + content: "\e049"; } + .glyphicon-text-height:before { - content: "\e050"; + content: "\e050"; } + .glyphicon-text-width:before { - content: "\e051"; + content: "\e051"; } + .glyphicon-align-left:before { - content: "\e052"; + content: "\e052"; } + .glyphicon-align-center:before { - content: "\e053"; + content: "\e053"; } + .glyphicon-align-right:before { - content: "\e054"; + content: "\e054"; } + .glyphicon-align-justify:before { - content: "\e055"; + content: "\e055"; } + .glyphicon-list:before { - content: "\e056"; + content: "\e056"; } + .glyphicon-indent-left:before { - content: "\e057"; + content: "\e057"; } + .glyphicon-indent-right:before { - content: "\e058"; + content: "\e058"; } + .glyphicon-facetime-video:before { - content: "\e059"; + content: "\e059"; } + .glyphicon-picture:before { - content: "\e060"; + content: "\e060"; } + .glyphicon-map-marker:before { - content: "\e062"; + content: "\e062"; } + .glyphicon-adjust:before { - content: "\e063"; + content: "\e063"; } + .glyphicon-tint:before { - content: "\e064"; + content: "\e064"; } + .glyphicon-edit:before { - content: "\e065"; + content: "\e065"; } + .glyphicon-share:before { - content: "\e066"; + content: "\e066"; } + .glyphicon-check:before { - content: "\e067"; + content: "\e067"; } + .glyphicon-move:before { - content: "\e068"; + content: "\e068"; } + .glyphicon-step-backward:before { - content: "\e069"; + content: "\e069"; } + .glyphicon-fast-backward:before { - content: "\e070"; + content: "\e070"; } + .glyphicon-backward:before { - content: "\e071"; + content: "\e071"; } + .glyphicon-play:before { - content: "\e072"; + content: "\e072"; } + .glyphicon-pause:before { - content: "\e073"; + content: "\e073"; } + .glyphicon-stop:before { - content: "\e074"; + content: "\e074"; } + .glyphicon-forward:before { - content: "\e075"; + content: "\e075"; } + .glyphicon-fast-forward:before { - content: "\e076"; + content: "\e076"; } + .glyphicon-step-forward:before { - content: "\e077"; + content: "\e077"; } + .glyphicon-eject:before { - content: "\e078"; + content: "\e078"; } + .glyphicon-chevron-left:before { - content: "\e079"; + content: "\e079"; } + .glyphicon-chevron-right:before { - content: "\e080"; + content: "\e080"; } + .glyphicon-plus-sign:before { - content: "\e081"; + content: "\e081"; } + .glyphicon-minus-sign:before { - content: "\e082"; + content: "\e082"; } + .glyphicon-remove-sign:before { - content: "\e083"; + content: "\e083"; } + .glyphicon-ok-sign:before { - content: "\e084"; + content: "\e084"; } + .glyphicon-question-sign:before { - content: "\e085"; + content: "\e085"; } + .glyphicon-info-sign:before { - content: "\e086"; + content: "\e086"; } + .glyphicon-screenshot:before { - content: "\e087"; + content: "\e087"; } + .glyphicon-remove-circle:before { - content: "\e088"; + content: "\e088"; } + .glyphicon-ok-circle:before { - content: "\e089"; + content: "\e089"; } + .glyphicon-ban-circle:before { - content: "\e090"; + content: "\e090"; } + .glyphicon-arrow-left:before { - content: "\e091"; + content: "\e091"; } + .glyphicon-arrow-right:before { - content: "\e092"; + content: "\e092"; } + .glyphicon-arrow-up:before { - content: "\e093"; + content: "\e093"; } + .glyphicon-arrow-down:before { - content: "\e094"; + content: "\e094"; } + .glyphicon-share-alt:before { - content: "\e095"; + content: "\e095"; } + .glyphicon-resize-full:before { - content: "\e096"; + content: "\e096"; } + .glyphicon-resize-small:before { - content: "\e097"; + content: "\e097"; } + .glyphicon-exclamation-sign:before { - content: "\e101"; + content: "\e101"; } + .glyphicon-gift:before { - content: "\e102"; + content: "\e102"; } + .glyphicon-leaf:before { - content: "\e103"; + content: "\e103"; } + .glyphicon-fire:before { - content: "\e104"; + content: "\e104"; } + .glyphicon-eye-open:before { - content: "\e105"; + content: "\e105"; } + .glyphicon-eye-close:before { - content: "\e106"; + content: "\e106"; } + .glyphicon-warning-sign:before { - content: "\e107"; + content: "\e107"; } + .glyphicon-plane:before { - content: "\e108"; + content: "\e108"; } + .glyphicon-calendar:before { - content: "\e109"; + content: "\e109"; } + .glyphicon-random:before { - content: "\e110"; + content: "\e110"; } + .glyphicon-comment:before { - content: "\e111"; + content: "\e111"; } + .glyphicon-magnet:before { - content: "\e112"; + content: "\e112"; } + .glyphicon-chevron-up:before { - content: "\e113"; + content: "\e113"; } + .glyphicon-chevron-down:before { - content: "\e114"; + content: "\e114"; } + .glyphicon-retweet:before { - content: "\e115"; + content: "\e115"; } + .glyphicon-shopping-cart:before { - content: "\e116"; + content: "\e116"; } + .glyphicon-folder-close:before { - content: "\e117"; + content: "\e117"; } + .glyphicon-folder-open:before { - content: "\e118"; + content: "\e118"; } + .glyphicon-resize-vertical:before { - content: "\e119"; + content: "\e119"; } + .glyphicon-resize-horizontal:before { - content: "\e120"; + content: "\e120"; } + .glyphicon-hdd:before { - content: "\e121"; + content: "\e121"; } + .glyphicon-bullhorn:before { - content: "\e122"; + content: "\e122"; } + .glyphicon-bell:before { - content: "\e123"; + content: "\e123"; } + .glyphicon-certificate:before { - content: "\e124"; + content: "\e124"; } + .glyphicon-thumbs-up:before { - content: "\e125"; + content: "\e125"; } + .glyphicon-thumbs-down:before { - content: "\e126"; + content: "\e126"; } + .glyphicon-hand-right:before { - content: "\e127"; + content: "\e127"; } + .glyphicon-hand-left:before { - content: "\e128"; + content: "\e128"; } + .glyphicon-hand-up:before { - content: "\e129"; + content: "\e129"; } + .glyphicon-hand-down:before { - content: "\e130"; + content: "\e130"; } + .glyphicon-circle-arrow-right:before { - content: "\e131"; + content: "\e131"; } + .glyphicon-circle-arrow-left:before { - content: "\e132"; + content: "\e132"; } + .glyphicon-circle-arrow-up:before { - content: "\e133"; + content: "\e133"; } + .glyphicon-circle-arrow-down:before { - content: "\e134"; + content: "\e134"; } + .glyphicon-globe:before { - content: "\e135"; + content: "\e135"; } + .glyphicon-wrench:before { - content: "\e136"; + content: "\e136"; } + .glyphicon-tasks:before { - content: "\e137"; + content: "\e137"; } + .glyphicon-filter:before { - content: "\e138"; + content: "\e138"; } + .glyphicon-briefcase:before { - content: "\e139"; + content: "\e139"; } + .glyphicon-fullscreen:before { - content: "\e140"; + content: "\e140"; } + .glyphicon-dashboard:before { - content: "\e141"; + content: "\e141"; } + .glyphicon-paperclip:before { - content: "\e142"; + content: "\e142"; } + .glyphicon-heart-empty:before { - content: "\e143"; + content: "\e143"; } + .glyphicon-link:before { - content: "\e144"; + content: "\e144"; } + .glyphicon-phone:before { - content: "\e145"; + content: "\e145"; } + .glyphicon-pushpin:before { - content: "\e146"; + content: "\e146"; } + .glyphicon-usd:before { - content: "\e148"; + content: "\e148"; } + .glyphicon-gbp:before { - content: "\e149"; + content: "\e149"; } + .glyphicon-sort:before { - content: "\e150"; + content: "\e150"; } + .glyphicon-sort-by-alphabet:before { - content: "\e151"; + content: "\e151"; } + .glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; + content: "\e152"; } + .glyphicon-sort-by-order:before { - content: "\e153"; + content: "\e153"; } + .glyphicon-sort-by-order-alt:before { - content: "\e154"; + content: "\e154"; } + .glyphicon-sort-by-attributes:before { - content: "\e155"; + content: "\e155"; } + .glyphicon-sort-by-attributes-alt:before { - content: "\e156"; + content: "\e156"; } + .glyphicon-unchecked:before { - content: "\e157"; + content: "\e157"; } + .glyphicon-expand:before { - content: "\e158"; + content: "\e158"; } + .glyphicon-collapse-down:before { - content: "\e159"; + content: "\e159"; } + .glyphicon-collapse-up:before { - content: "\e160"; + content: "\e160"; } + .glyphicon-log-in:before { - content: "\e161"; + content: "\e161"; } + .glyphicon-flash:before { - content: "\e162"; + content: "\e162"; } + .glyphicon-log-out:before { - content: "\e163"; + content: "\e163"; } + .glyphicon-new-window:before { - content: "\e164"; + content: "\e164"; } + .glyphicon-record:before { - content: "\e165"; + content: "\e165"; } + .glyphicon-save:before { - content: "\e166"; + content: "\e166"; } + .glyphicon-open:before { - content: "\e167"; + content: "\e167"; } + .glyphicon-saved:before { - content: "\e168"; + content: "\e168"; } + .glyphicon-import:before { - content: "\e169"; + content: "\e169"; } + .glyphicon-export:before { - content: "\e170"; + content: "\e170"; } + .glyphicon-send:before { - content: "\e171"; + content: "\e171"; } + .glyphicon-floppy-disk:before { - content: "\e172"; + content: "\e172"; } + .glyphicon-floppy-saved:before { - content: "\e173"; + content: "\e173"; } + .glyphicon-floppy-remove:before { - content: "\e174"; + content: "\e174"; } + .glyphicon-floppy-save:before { - content: "\e175"; + content: "\e175"; } + .glyphicon-floppy-open:before { - content: "\e176"; + content: "\e176"; } + .glyphicon-credit-card:before { - content: "\e177"; + content: "\e177"; } + .glyphicon-transfer:before { - content: "\e178"; + content: "\e178"; } + .glyphicon-cutlery:before { - content: "\e179"; + content: "\e179"; } + .glyphicon-header:before { - content: "\e180"; + content: "\e180"; } + .glyphicon-compressed:before { - content: "\e181"; + content: "\e181"; } + .glyphicon-earphone:before { - content: "\e182"; + content: "\e182"; } + .glyphicon-phone-alt:before { - content: "\e183"; + content: "\e183"; } + .glyphicon-tower:before { - content: "\e184"; + content: "\e184"; } + .glyphicon-stats:before { - content: "\e185"; + content: "\e185"; } + .glyphicon-sd-video:before { - content: "\e186"; + content: "\e186"; } + .glyphicon-hd-video:before { - content: "\e187"; + content: "\e187"; } + .glyphicon-subtitles:before { - content: "\e188"; + content: "\e188"; } + .glyphicon-sound-stereo:before { - content: "\e189"; + content: "\e189"; } + .glyphicon-sound-dolby:before { - content: "\e190"; + content: "\e190"; } + .glyphicon-sound-5-1:before { - content: "\e191"; + content: "\e191"; } + .glyphicon-sound-6-1:before { - content: "\e192"; + content: "\e192"; } + .glyphicon-sound-7-1:before { - content: "\e193"; + content: "\e193"; } + .glyphicon-copyright-mark:before { - content: "\e194"; + content: "\e194"; } + .glyphicon-registration-mark:before { - content: "\e195"; + content: "\e195"; } + .glyphicon-cloud-download:before { - content: "\e197"; + content: "\e197"; } + .glyphicon-cloud-upload:before { - content: "\e198"; + content: "\e198"; } + .glyphicon-tree-conifer:before { - content: "\e199"; + content: "\e199"; } + .glyphicon-tree-deciduous:before { - content: "\e200"; + content: "\e200"; } + .caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px solid; - border-right: 4px solid transparent; - border-left: 4px solid transparent; + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; } + .dropdown { - position: relative; + position: relative; } + .dropdown-toggle:focus { - outline: 0; + outline: 0; } + .dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - list-style: none; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); } + .dropdown-menu.pull-right { - right: 0; - left: auto; + right: 0; + left: auto; } + .dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; } + .dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; } + .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; + color: #262626; + text-decoration: none; + background-color: #f5f5f5; } + .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #428bca; - outline: 0; + color: #fff; + text-decoration: none; + background-color: #428bca; + outline: 0; } + .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { - color: #999; + color: #999; } + .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } + .open > .dropdown-menu { - display: block; + display: block; } + .open > a { - outline: 0; + outline: 0; } + .dropdown-menu-right { - right: 0; - left: auto; + right: 0; + left: auto; } + .dropdown-menu-left { - right: auto; - left: 0; + right: auto; + left: 0; } + .dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #999; + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999; } + .dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; } + .pull-right > .dropdown-menu { - right: 0; - left: auto; + right: 0; + left: auto; } + .dropup .caret, .navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px solid; + content: ""; + border-top: 0; + border-bottom: 4px solid; } + .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; + top: auto; + bottom: 100%; + margin-bottom: 1px; } + @media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } } + .btn-group, .btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; + position: relative; + display: inline-block; + vertical-align: middle; } + .btn-group > .btn, .btn-group-vertical > .btn { - position: relative; - float: left; + position: relative; + float: left; } + .btn-group > .btn:hover, .btn-group-vertical > .btn:hover, .btn-group > .btn:focus, @@ -3147,256 +3883,307 @@ input[type="button"].btn-block { .btn-group-vertical > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn.active { - z-index: 2; + z-index: 2; } + .btn-group > .btn:focus, .btn-group-vertical > .btn:focus { - outline: none; + outline: none; } + .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group { - margin-left: -1px; + margin-left: -1px; } + .btn-toolbar { - margin-left: -5px; + margin-left: -5px; } + .btn-toolbar .btn-group, .btn-toolbar .input-group { - float: left; + float: left; } + .btn-toolbar > .btn, .btn-toolbar > .btn-group, .btn-toolbar > .input-group { - margin-left: 5px; + margin-left: 5px; } + .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; + border-radius: 0; } + .btn-group > .btn:first-child { - margin-left: 0; + margin-left: 0; } + .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .btn-group > .btn-group { - float: left; + float: left; } + .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; + border-radius: 0; } + .btn-group > .btn-group:first-child > .btn:last-child, .btn-group > .btn-group:first-child > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .btn-group > .btn-group:last-child > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { - outline: 0; + outline: 0; } + .btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; + padding-right: 8px; + padding-left: 8px; } + .btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; + padding-right: 12px; + padding-left: 12px; } + .btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } + .btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; } + .btn .caret { - margin-left: 0; + margin-left: 0; } + .btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; + border-width: 5px 5px 0; + border-bottom-width: 0; } + .dropup .btn-lg .caret { - border-width: 0 5px 5px; + border-width: 0 5px 5px; } + .btn-group-vertical > .btn, .btn-group-vertical > .btn-group, .btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; + display: block; + float: none; + width: 100%; + max-width: 100%; } + .btn-group-vertical > .btn-group > .btn { - float: none; + float: none; } + .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; + margin-top: -1px; + margin-left: 0; } + .btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; + border-radius: 0; } + .btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + .btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 4px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; } + .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; + border-radius: 0; } + .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; } + .btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; } + .btn-group-justified > .btn, .btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; + display: table-cell; + float: none; + width: 1%; } + .btn-group-justified > .btn-group .btn { - width: 100%; + width: 100%; } + [data-toggle="buttons"] > .btn > input[type="radio"], [data-toggle="buttons"] > .btn > input[type="checkbox"] { - display: none; + display: none; } + .input-group { - position: relative; - display: table; - border-collapse: separate; + position: relative; + display: table; + border-collapse: separate; } + .input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; + float: none; + padding-right: 0; + padding-left: 0; } + .input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; } + .input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; } + select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; + height: 46px; + line-height: 46px; } + textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-addon, textarea.input-group-lg > .input-group-btn > .btn, select[multiple].input-group-lg > .form-control, select[multiple].input-group-lg > .input-group-addon, select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; + height: auto; } + .input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; + height: 30px; + line-height: 30px; } + textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-addon, textarea.input-group-sm > .input-group-btn > .btn, select[multiple].input-group-sm > .form-control, select[multiple].input-group-sm > .input-group-addon, select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; + height: auto; } + .input-group-addon, .input-group-btn, .input-group .form-control { - display: table-cell; + display: table-cell; } + .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; + border-radius: 0; } + .input-group-addon, .input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; + width: 1%; + white-space: nowrap; + vertical-align: middle; } + .input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px; + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; } + .input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; } + .input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; } + .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { - margin-top: 0; + margin-top: 0; } + .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child > .btn, @@ -3404,12 +4191,14 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .input-group-btn:first-child > .dropdown-toggle, .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .input-group-addon:first-child { - border-right: 0; + border-right: 0; } + .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child > .btn, @@ -3417,1407 +4206,1704 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .input-group-btn:last-child > .dropdown-toggle, .input-group-btn:first-child > .btn:not(:first-child), .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .input-group-addon:last-child { - border-left: 0; + border-left: 0; } + .input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; + position: relative; + font-size: 0; + white-space: nowrap; } + .input-group-btn > .btn { - position: relative; + position: relative; } + .input-group-btn > .btn + .btn { - margin-left: -1px; + margin-left: -1px; } + .input-group-btn > .btn:hover, .input-group-btn > .btn:focus, .input-group-btn > .btn:active { - z-index: 2; + z-index: 2; } + .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group { - margin-right: -1px; + margin-right: -1px; } + .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group { - margin-left: -1px; + margin-left: -1px; } + .nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; + padding-left: 0; + margin-bottom: 0; + list-style: none; } + .nav > li { - position: relative; - display: block; + position: relative; + display: block; } + .nav > li > a { - position: relative; - display: block; - padding: 10px 15px; + position: relative; + display: block; + padding: 10px 15px; } + .nav > li > a:hover, .nav > li > a:focus { - text-decoration: none; - background-color: #eee; + text-decoration: none; + background-color: #eee; } + .nav > li.disabled > a { - color: #999; + color: #999; } + .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { - color: #999; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; + color: #999; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; } + .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { - background-color: #eee; - border-color: #428bca; + background-color: #eee; + border-color: #428bca; } + .nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; } + .nav > li > a > img { - max-width: none; + max-width: none; } + .nav-tabs { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #ddd; } + .nav-tabs > li { - float: left; - margin-bottom: -1px; + float: left; + margin-bottom: -1px; } + .nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; } + .nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; + border-color: #eee #eee #ddd; } + .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; } + .nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; + width: 100%; + border-bottom: 0; } + .nav-tabs.nav-justified > li { - float: none; + float: none; } + .nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; + margin-bottom: 5px; + text-align: center; } + .nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; + top: auto; + left: auto; } + @media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } } + .nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; + margin-right: 0; + border-radius: 4px; } + .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; + border: 1px solid #ddd; } + @media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } } + .nav-pills > li { - float: left; + float: left; } + .nav-pills > li > a { - border-radius: 4px; + border-radius: 4px; } + .nav-pills > li + li { - margin-left: 2px; + margin-left: 2px; } + .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { - color: #fff; - background-color: #428bca; + color: #fff; + background-color: #428bca; } + .nav-stacked > li { - float: none; + float: none; } + .nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; + margin-top: 2px; + margin-left: 0; } + .nav-justified { - width: 100%; + width: 100%; } + .nav-justified > li { - float: none; + float: none; } + .nav-justified > li > a { - margin-bottom: 5px; - text-align: center; + margin-bottom: 5px; + text-align: center; } + .nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; + top: auto; + left: auto; } + @media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } + .nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-justified > li > a { + margin-bottom: 0; + } } + .nav-tabs-justified { - border-bottom: 0; + border-bottom: 0; } + .nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; + margin-right: 0; + border-radius: 4px; } + .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; + border: 1px solid #ddd; } + @media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } } + .tab-content > .tab-pane { - display: none; + display: none; } + .tab-content > .active { - display: block; + display: block; } + .nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; } + .navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; } + @media (min-width: 768px) { - .navbar { - border-radius: 4px; - } + .navbar { + border-radius: 4px; + } } + @media (min-width: 768px) { - .navbar-header { - float: left; - } + .navbar-header { + float: left; + } } + .navbar-collapse { - max-height: 340px; - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + max-height: 340px; + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); } + .navbar-collapse.in { - overflow-y: auto; + overflow-y: auto; } + @media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + + .navbar-collapse.in { + overflow-y: visible; + } + + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } } + .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; + margin-right: -15px; + margin-left: -15px; } + @media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } } + .navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; + z-index: 1000; + border-width: 0 0 1px; } + @media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } + .navbar-static-top { + border-radius: 0; + } } + .navbar-fixed-top, .navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; + position: fixed; + right: 0; + left: 0; + z-index: 1030; } + @media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } } + .navbar-fixed-top { - top: 0; - border-width: 0 0 1px; + top: 0; + border-width: 0 0 1px; } + .navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; } + .navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; } + .navbar-brand:hover, .navbar-brand:focus { - text-decoration: none; + text-decoration: none; } + @media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } } + .navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; } + .navbar-toggle:focus { - outline: none; + outline: none; } + .navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; + display: block; + width: 22px; + height: 2px; + border-radius: 1px; } + .navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; + margin-top: 4px; } + @media (min-width: 768px) { - .navbar-toggle { - display: none; - } + .navbar-toggle { + display: none; + } } + .navbar-nav { - margin: 7.5px -15px; + margin: 7.5px -15px; } + .navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; } + @media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } } + @media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } - .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } + .navbar-nav { + float: left; + margin: 0; + } + + .navbar-nav > li { + float: left; + } + + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } + + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } } + @media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } + .navbar-left { + float: left !important; + } + + .navbar-right { + float: right !important; + } } + .navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); } + @media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .navbar-form .input-group > .form-control { + width: 100%; + } + + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } } + @media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } + .navbar-form .form-group { + margin-bottom: 5px; + } } + @media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-form.navbar-right:last-child { - margin-right: -15px; - } + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } } + .navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; } + .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + .navbar-btn { - margin-top: 8px; - margin-bottom: 8px; + margin-top: 8px; + margin-bottom: 8px; } + .navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; + margin-top: 10px; + margin-bottom: 10px; } + .navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; + margin-top: 14px; + margin-bottom: 14px; } + .navbar-text { - margin-top: 15px; - margin-bottom: 15px; + margin-top: 15px; + margin-bottom: 15px; } + @media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } - .navbar-text.navbar-right:last-child { - margin-right: 0; - } + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } + + .navbar-text.navbar-right:last-child { + margin-right: 0; + } } + .navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; + background-color: #f8f8f8; + border-color: #e7e7e7; } + .navbar-default .navbar-brand { - color: #777; + color: #777; } + .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; + color: #5e5e5e; + background-color: transparent; } + .navbar-default .navbar-text { - color: #777; + color: #777; } + .navbar-default .navbar-nav > li > a { - color: #777; + color: #777; } + .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; + color: #333; + background-color: transparent; } + .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; + color: #555; + background-color: #e7e7e7; } + .navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; + color: #ccc; + background-color: transparent; } + .navbar-default .navbar-toggle { - border-color: #ddd; + border-color: #ddd; } + .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { - background-color: #ddd; + background-color: #ddd; } + .navbar-default .navbar-toggle .icon-bar { - background-color: #888; + background-color: #888; } + .navbar-default .navbar-collapse, .navbar-default .navbar-form { - border-color: #e7e7e7; + border-color: #e7e7e7; } + .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { color: #555; background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #ccc; - background-color: transparent; - } } + +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} + .navbar-default .navbar-link { - color: #777; + color: #777; } + .navbar-default .navbar-link:hover { - color: #333; + color: #333; } + .navbar-inverse { - background-color: #222; - border-color: #080808; + background-color: #222; + border-color: #080808; } + .navbar-inverse .navbar-brand { - color: #999; + color: #999; } + .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; + color: #fff; + background-color: transparent; } + .navbar-inverse .navbar-text { - color: #999; + color: #999; } + .navbar-inverse .navbar-nav > li > a { - color: #999; + color: #999; } + .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; + color: #fff; + background-color: transparent; } + .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; + color: #fff; + background-color: #080808; } + .navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; + color: #444; + background-color: transparent; } + .navbar-inverse .navbar-toggle { - border-color: #333; + border-color: #333; } + .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { - background-color: #333; + background-color: #333; } + .navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; + background-color: #fff; } + .navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #999; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { +.navbar-inverse .navbar-form { + border-color: #101010; +} + +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { color: #fff; background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444; - background-color: transparent; - } } + +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} + .navbar-inverse .navbar-link { - color: #999; + color: #999; } + .navbar-inverse .navbar-link:hover { - color: #fff; + color: #fff; } + .breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; } + .breadcrumb > li { - display: inline-block; + display: inline-block; } + .breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; + padding: 0 5px; + color: #ccc; + content: "/\00a0"; } + .breadcrumb > .active { - color: #999; + color: #999; } + .pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; } + .pagination > li { - display: inline; + display: inline; } + .pagination > li > a, .pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #428bca; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #428bca; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; } + .pagination > li:first-child > a, .pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; } + .pagination > li:last-child > a, .pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; } + .pagination > li > a:hover, .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { - color: #2a6496; - background-color: #eee; - border-color: #ddd; + color: #2a6496; + background-color: #eee; + border-color: #ddd; } + .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus { - z-index: 2; - color: #fff; - cursor: default; - background-color: #428bca; - border-color: #428bca; + z-index: 2; + color: #fff; + cursor: default; + background-color: #428bca; + border-color: #428bca; } + .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { - color: #999; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; + color: #999; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; } + .pagination-lg > li > a, .pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; + padding: 10px 16px; + font-size: 18px; } + .pagination-lg > li:first-child > a, .pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; } + .pagination-lg > li:last-child > a, .pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; } + .pagination-sm > li > a, .pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; + padding: 5px 10px; + font-size: 12px; } + .pagination-sm > li:first-child > a, .pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } + .pagination-sm > li:last-child > a, .pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } + .pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; } + .pager li { - display: inline; + display: inline; } + .pager li > a, .pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; } + .pager li > a:hover, .pager li > a:focus { - text-decoration: none; - background-color: #eee; + text-decoration: none; + background-color: #eee; } + .pager .next > a, .pager .next > span { - float: right; + float: right; } + .pager .previous > a, .pager .previous > span { - float: left; + float: left; } + .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { - color: #999; - cursor: not-allowed; - background-color: #fff; + color: #999; + cursor: not-allowed; + background-color: #fff; } + .label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; } + .label[href]:hover, .label[href]:focus { - color: #fff; - text-decoration: none; - cursor: pointer; + color: #fff; + text-decoration: none; + cursor: pointer; } + .label:empty { - display: none; + display: none; } + .btn .label { - position: relative; - top: -1px; + position: relative; + top: -1px; } + .label-default { - background-color: #999; + background-color: #999; } + .label-default[href]:hover, .label-default[href]:focus { - background-color: #808080; + background-color: #808080; } + .label-primary { - background-color: #428bca; + background-color: #428bca; } + .label-primary[href]:hover, .label-primary[href]:focus { - background-color: #3071a9; + background-color: #3071a9; } + .label-success { - background-color: #5cb85c; + background-color: #5cb85c; } + .label-success[href]:hover, .label-success[href]:focus { - background-color: #449d44; + background-color: #449d44; } + .label-info { - background-color: #5bc0de; + background-color: #5bc0de; } + .label-info[href]:hover, .label-info[href]:focus { - background-color: #31b0d5; + background-color: #31b0d5; } + .label-warning { - background-color: #f0ad4e; + background-color: #f0ad4e; } + .label-warning[href]:hover, .label-warning[href]:focus { - background-color: #ec971f; + background-color: #ec971f; } + .label-danger { - background-color: #d9534f; + background-color: #d9534f; } + .label-danger[href]:hover, .label-danger[href]:focus { - background-color: #c9302c; + background-color: #c9302c; } + .badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #999; - border-radius: 10px; + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999; + border-radius: 10px; } + .badge:empty { - display: none; + display: none; } + .btn .badge { - position: relative; - top: -1px; + position: relative; + top: -1px; } + .btn-xs .badge { - top: 0; - padding: 1px 5px; + top: 0; + padding: 1px 5px; } + a.badge:hover, a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; + color: #fff; + text-decoration: none; + cursor: pointer; } + a.list-group-item.active > .badge, .nav-pills > .active > a > .badge { - color: #428bca; - background-color: #fff; + color: #428bca; + background-color: #fff; } + .nav-pills > li > a > .badge { - margin-left: 3px; + margin-left: 3px; } + .jumbotron { - padding: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eee; + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; } + .jumbotron h1, .jumbotron .h1 { - color: inherit; + color: inherit; } + .jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; } + .container .jumbotron { - border-radius: 6px; + border-radius: 6px; } + .jumbotron .container { - max-width: 100%; + max-width: 100%; } + @media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + + .container .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } } + .thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; } + .thumbnail > img, .thumbnail a > img { - margin-right: auto; - margin-left: auto; + margin-right: auto; + margin-left: auto; } + a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { - border-color: #428bca; + border-color: #428bca; } + .thumbnail .caption { - padding: 9px; - color: #333; + padding: 9px; + color: #333; } + .alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; } + .alert h4 { - margin-top: 0; - color: inherit; + margin-top: 0; + color: inherit; } + .alert .alert-link { - font-weight: bold; + font-weight: bold; } + .alert > p, .alert > ul { - margin-bottom: 0; + margin-bottom: 0; } + .alert > p + p { - margin-top: 5px; + margin-top: 5px; } + .alert-dismissable { - padding-right: 35px; + padding-right: 35px; } + .alert-dismissable .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; + position: relative; + top: -2px; + right: -21px; + color: inherit; } + .alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; } + .alert-success hr { - border-top-color: #c9e2b3; + border-top-color: #c9e2b3; } + .alert-success .alert-link { - color: #2b542c; + color: #2b542c; } + .alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; } + .alert-info hr { - border-top-color: #a6e1ec; + border-top-color: #a6e1ec; } + .alert-info .alert-link { - color: #245269; + color: #245269; } + .alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; } + .alert-warning hr { - border-top-color: #f7e1b5; + border-top-color: #f7e1b5; } + .alert-warning .alert-link { - color: #66512c; + color: #66512c; } + .alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; } + .alert-danger hr { - border-top-color: #e4b9c0; + border-top-color: #e4b9c0; } + .alert-danger .alert-link { - color: #843534; + color: #843534; } + @-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } } + @keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } } + .progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); } + .progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #428bca; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - transition: width .6s ease; + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + transition: width .6s ease; } + .progress-striped .progress-bar { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-size: 40px 40px; + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-size: 40px 40px; } + .progress.active .progress-bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; + -webkit-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; } + .progress-bar-success { - background-color: #5cb85c; + background-color: #5cb85c; } + .progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } + .progress-bar-info { - background-color: #5bc0de; + background-color: #5bc0de; } + .progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } + .progress-bar-warning { - background-color: #f0ad4e; + background-color: #f0ad4e; } + .progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } + .progress-bar-danger { - background-color: #d9534f; + background-color: #d9534f; } + .progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } + .media, .media-body { - overflow: hidden; - zoom: 1; + overflow: hidden; + zoom: 1; } + .media, .media .media { - margin-top: 15px; + margin-top: 15px; } + .media:first-child { - margin-top: 0; + margin-top: 0; } + .media-object { - display: block; + display: block; } + .media-heading { - margin: 0 0 5px; + margin: 0 0 5px; } + .media > .pull-left { - margin-right: 10px; + margin-right: 10px; } + .media > .pull-right { - margin-left: 10px; + margin-left: 10px; } + .media-list { - padding-left: 0; - list-style: none; + padding-left: 0; + list-style: none; } + .list-group { - padding-left: 0; - margin-bottom: 20px; + padding-left: 0; + margin-bottom: 20px; } + .list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; } + .list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; } + .list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; } + .list-group-item > .badge { - float: right; + float: right; } + .list-group-item > .badge + .badge { - margin-right: 5px; + margin-right: 5px; } + a.list-group-item { - color: #555; + color: #555; } + a.list-group-item .list-group-item-heading { - color: #333; + color: #333; } + a.list-group-item:hover, a.list-group-item:focus { - text-decoration: none; - background-color: #f5f5f5; + text-decoration: none; + background-color: #f5f5f5; } + a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #428bca; - border-color: #428bca; + z-index: 2; + color: #fff; + background-color: #428bca; + border-color: #428bca; } + a.list-group-item.active .list-group-item-heading, a.list-group-item.active:hover .list-group-item-heading, a.list-group-item.active:focus .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item.active .list-group-item-text, a.list-group-item.active:hover .list-group-item-text, a.list-group-item.active:focus .list-group-item-text { - color: #e1edf7; + color: #e1edf7; } + .list-group-item-success { - color: #3c763d; - background-color: #dff0d8; + color: #3c763d; + background-color: #dff0d8; } + a.list-group-item-success { - color: #3c763d; + color: #3c763d; } + a.list-group-item-success .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-success:hover, a.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; + color: #3c763d; + background-color: #d0e9c6; } + a.list-group-item-success.active, a.list-group-item-success.active:hover, a.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; + color: #fff; + background-color: #3c763d; + border-color: #3c763d; } + .list-group-item-info { - color: #31708f; - background-color: #d9edf7; + color: #31708f; + background-color: #d9edf7; } + a.list-group-item-info { - color: #31708f; + color: #31708f; } + a.list-group-item-info .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-info:hover, a.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; + color: #31708f; + background-color: #c4e3f3; } + a.list-group-item-info.active, a.list-group-item-info.active:hover, a.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; + color: #fff; + background-color: #31708f; + border-color: #31708f; } + .list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; + color: #8a6d3b; + background-color: #fcf8e3; } + a.list-group-item-warning { - color: #8a6d3b; + color: #8a6d3b; } + a.list-group-item-warning .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-warning:hover, a.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; + color: #8a6d3b; + background-color: #faf2cc; } + a.list-group-item-warning.active, a.list-group-item-warning.active:hover, a.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; } + .list-group-item-danger { - color: #a94442; - background-color: #f2dede; + color: #a94442; + background-color: #f2dede; } + a.list-group-item-danger { - color: #a94442; + color: #a94442; } + a.list-group-item-danger .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-danger:hover, a.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; + color: #a94442; + background-color: #ebcccc; } + a.list-group-item-danger.active, a.list-group-item-danger.active:hover, a.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; + color: #fff; + background-color: #a94442; + border-color: #a94442; } + .list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; + margin-top: 0; + margin-bottom: 5px; } + .list-group-item-text { - margin-bottom: 0; - line-height: 1.3; + margin-bottom: 0; + line-height: 1.3; } + .panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); } + .panel-body { - padding: 15px; + padding: 15px; } + .panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + .panel-heading > .dropdown .dropdown-toggle { - color: inherit; + color: inherit; } + .panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; } + .panel-title > a { - color: inherit; + color: inherit; } + .panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + .panel > .list-group { - margin-bottom: 0; + margin-bottom: 0; } + .panel > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; + border-width: 1px 0; + border-radius: 0; } + .panel > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + .panel > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + .panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; + border-top-width: 0; } + .panel > .table, .panel > .table-responsive > .table { - margin-bottom: 0; + margin-bottom: 0; } + .panel > .table:first-child, .panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, @@ -4826,8 +5912,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; + border-top-left-radius: 3px; } + .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, @@ -4836,13 +5923,15 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; + border-top-right-radius: 3px; } + .panel > .table:last-child, .panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, @@ -4851,8 +5940,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; } + .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, @@ -4861,20 +5951,24 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; } + .panel > .panel-body + .table, .panel > .panel-body + .table-responsive { - border-top: 1px solid #ddd; + border-top: 1px solid #ddd; } + .panel > .table > tbody:first-child > tr:first-child th, .panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; + border-top: 0; } + .panel > .table-bordered, .panel > .table-responsive > .table-bordered { - border: 0; + border: 0; } + .panel > .table-bordered > thead > tr > th:first-child, .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, .panel > .table-bordered > tbody > tr > th:first-child, @@ -4887,8 +5981,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, .panel > .table-bordered > tfoot > tr > td:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; + border-left: 0; } + .panel > .table-bordered > thead > tr > th:last-child, .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, .panel > .table-bordered > tbody > tr > th:last-child, @@ -4901,8 +5996,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, .panel > .table-bordered > tfoot > tr > td:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; + border-right: 0; } + .panel > .table-bordered > thead > tr:first-child > td, .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, .panel > .table-bordered > tbody > tr:first-child > td, @@ -4911,8 +6007,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, .panel > .table-bordered > tbody > tr:first-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; + border-bottom: 0; } + .panel > .table-bordered > tbody > tr:last-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, .panel > .table-bordered > tfoot > tr:last-child > td, @@ -4921,674 +6018,799 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, .panel > .table-bordered > tfoot > tr:last-child > th, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; + border-bottom: 0; } + .panel > .table-responsive { - margin-bottom: 0; - border: 0; + margin-bottom: 0; + border: 0; } + .panel-group { - margin-bottom: 20px; + margin-bottom: 20px; } + .panel-group .panel { - margin-bottom: 0; - overflow: hidden; - border-radius: 4px; + margin-bottom: 0; + overflow: hidden; + border-radius: 4px; } + .panel-group .panel + .panel { - margin-top: 5px; + margin-top: 5px; } + .panel-group .panel-heading { - border-bottom: 0; + border-bottom: 0; } + .panel-group .panel-heading + .panel-collapse .panel-body { - border-top: 1px solid #ddd; + border-top: 1px solid #ddd; } + .panel-group .panel-footer { - border-top: 0; + border-top: 0; } + .panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #ddd; } + .panel-default { - border-color: #ddd; + border-color: #ddd; } + .panel-default > .panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd; + color: #333; + background-color: #f5f5f5; + border-color: #ddd; } + .panel-default > .panel-heading + .panel-collapse .panel-body { - border-top-color: #ddd; + border-top-color: #ddd; } + .panel-default > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #ddd; + border-bottom-color: #ddd; } + .panel-primary { - border-color: #428bca; + border-color: #428bca; } + .panel-primary > .panel-heading { - color: #fff; - background-color: #428bca; - border-color: #428bca; + color: #fff; + background-color: #428bca; + border-color: #428bca; } + .panel-primary > .panel-heading + .panel-collapse .panel-body { - border-top-color: #428bca; + border-top-color: #428bca; } + .panel-primary > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #428bca; + border-bottom-color: #428bca; } + .panel-success { - border-color: #d6e9c6; + border-color: #d6e9c6; } + .panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; } + .panel-success > .panel-heading + .panel-collapse .panel-body { - border-top-color: #d6e9c6; + border-top-color: #d6e9c6; } + .panel-success > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #d6e9c6; + border-bottom-color: #d6e9c6; } + .panel-info { - border-color: #bce8f1; + border-color: #bce8f1; } + .panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; } + .panel-info > .panel-heading + .panel-collapse .panel-body { - border-top-color: #bce8f1; + border-top-color: #bce8f1; } + .panel-info > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #bce8f1; + border-bottom-color: #bce8f1; } + .panel-warning { - border-color: #faebcc; + border-color: #faebcc; } + .panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; } + .panel-warning > .panel-heading + .panel-collapse .panel-body { - border-top-color: #faebcc; + border-top-color: #faebcc; } + .panel-warning > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #faebcc; + border-bottom-color: #faebcc; } + .panel-danger { - border-color: #ebccd1; + border-color: #ebccd1; } + .panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; } + .panel-danger > .panel-heading + .panel-collapse .panel-body { - border-top-color: #ebccd1; + border-top-color: #ebccd1; } + .panel-danger > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #ebccd1; + border-bottom-color: #ebccd1; } + .well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); } + .well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15); + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); } + .well-lg { - padding: 24px; - border-radius: 6px; + padding: 24px; + border-radius: 6px; } + .well-sm { - padding: 9px; - border-radius: 3px; + padding: 9px; + border-radius: 3px; } + .close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; } + .close:hover, .close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; } + button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; } + .modal-open { - overflow: hidden; + overflow: hidden; } + .modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: auto; - overflow-y: scroll; - -webkit-overflow-scrolling: touch; - outline: 0; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: auto; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + outline: 0; } + .modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -moz-transition: -moz-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - transform: translate(0, -25%); + -webkit-transition: -webkit-transform .3s ease-out; + -moz-transition: -moz-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); } + .modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); } + .modal-dialog { - position: relative; - width: auto; - margin: 10px; + position: relative; + width: auto; + margin: 10px; } + .modal-content { - position: relative; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + position: relative; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); } + .modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; } + .modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; + filter: alpha(opacity=0); + opacity: 0; } + .modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; + filter: alpha(opacity=50); + opacity: .5; } + .modal-header { - min-height: 16.42857143px; - padding: 15px; - border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; } + .modal-header .close { - margin-top: -2px; + margin-top: -2px; } + .modal-title { - margin: 0; - line-height: 1.42857143; + margin: 0; + line-height: 1.42857143; } + .modal-body { - position: relative; - padding: 20px; + position: relative; + padding: 20px; } + .modal-footer { - padding: 19px 20px 20px; - margin-top: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; + padding: 19px 20px 20px; + margin-top: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; } + .modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; + margin-bottom: 0; + margin-left: 5px; } + .modal-footer .btn-group .btn + .btn { - margin-left: -1px; + margin-left: -1px; } + .modal-footer .btn-block + .btn-block { - margin-left: 0; + margin-left: 0; } + @media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - } - .modal-sm { - width: 300px; - } + .modal-dialog { + width: 600px; + margin: 30px auto; + } + + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + + .modal-sm { + width: 300px; + } } + @media (min-width: 992px) { - .modal-lg { - width: 900px; - } + .modal-lg { + width: 900px; + } } + .tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 12px; - line-height: 1.4; - visibility: visible; - filter: alpha(opacity=0); - opacity: 0; + position: absolute; + z-index: 1030; + display: block; + font-size: 12px; + line-height: 1.4; + visibility: visible; + filter: alpha(opacity=0); + opacity: 0; } + .tooltip.in { - filter: alpha(opacity=90); - opacity: .9; + filter: alpha(opacity=90); + opacity: .9; } + .tooltip.top { - padding: 5px 0; - margin-top: -3px; + padding: 5px 0; + margin-top: -3px; } + .tooltip.right { - padding: 0 5px; - margin-left: 3px; + padding: 0 5px; + margin-left: 3px; } + .tooltip.bottom { - padding: 5px 0; - margin-top: 3px; + padding: 5px 0; + margin-top: 3px; } + .tooltip.left { - padding: 0 5px; - margin-left: -3px; + padding: 0 5px; + margin-left: -3px; } + .tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - text-decoration: none; - background-color: #000; - border-radius: 4px; + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; } + .tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; } + .tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; } + .tooltip.top-left .tooltip-arrow { - bottom: 0; - left: 5px; - border-width: 5px 5px 0; - border-top-color: #000; + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000; } + .tooltip.top-right .tooltip-arrow { - right: 5px; - bottom: 0; - border-width: 5px 5px 0; - border-top-color: #000; + right: 5px; + bottom: 0; + border-width: 5px 5px 0; + border-top-color: #000; } + .tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; } + .tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; } + .tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + .tooltip.bottom-left .tooltip-arrow { - top: 0; - left: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000; + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + .tooltip.bottom-right .tooltip-arrow { - top: 0; - right: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000; + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + .popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); } + .popover.top { - margin-top: -10px; + margin-top: -10px; } + .popover.right { - margin-left: 10px; + margin-left: 10px; } + .popover.bottom { - margin-top: 10px; + margin-top: 10px; } + .popover.left { - margin-left: -10px; + margin-left: -10px; } + .popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; } + .popover-content { - padding: 9px 14px; + padding: 9px 14px; } + .popover > .arrow, .popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; } + .popover > .arrow { - border-width: 11px; + border-width: 11px; } + .popover > .arrow:after { - content: ""; - border-width: 10px; + content: ""; + border-width: 10px; } + .popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; } + .popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; } + .popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; } + .popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; } + .popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); } + .popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; } + .popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); } + .popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; } + .carousel { - position: relative; + position: relative; } + .carousel-inner { - position: relative; - width: 100%; - overflow: hidden; + position: relative; + width: 100%; + overflow: hidden; } + .carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; } + .carousel-inner > .item > img, .carousel-inner > .item > a > img { - line-height: 1; + line-height: 1; } + .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { - display: block; + display: block; } + .carousel-inner > .active { - left: 0; + left: 0; } + .carousel-inner > .next, .carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; + position: absolute; + top: 0; + width: 100%; } + .carousel-inner > .next { - left: 100%; + left: 100%; } + .carousel-inner > .prev { - left: -100%; + left: -100%; } + .carousel-inner > .next.left, .carousel-inner > .prev.right { - left: 0; + left: 0; } + .carousel-inner > .active.left { - left: -100%; + left: -100%; } + .carousel-inner > .active.right { - left: 100%; + left: 100%; } + .carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - filter: alpha(opacity=50); - opacity: .5; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; } + .carousel-control.left { - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%)); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; } + .carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%)); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; } + .carousel-control:hover, .carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: none; - opacity: .9; + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: none; + opacity: .9; } + .carousel-control .icon-prev, .carousel-control .icon-next, .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; } + .carousel-control .icon-prev, .carousel-control .glyphicon-chevron-left { - left: 50%; + left: 50%; } + .carousel-control .icon-next, .carousel-control .glyphicon-chevron-right { - right: 50%; + right: 50%; } + .carousel-control .icon-prev, .carousel-control .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - margin-left: -10px; - font-family: serif; + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; } + .carousel-control .icon-prev:before { - content: '\2039'; + content: '\2039'; } + .carousel-control .icon-next:before { - content: '\203a'; + content: '\203a'; } + .carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; } + .carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; } + .carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; } + .carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); } + .carousel-caption .btn { - text-shadow: none; + text-shadow: none; } + @media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - margin-left: -15px; - font-size: 30px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + + .carousel-indicators { + bottom: 20px; + } } + .clearfix:before, .clearfix:after, .container:before, @@ -5617,9 +6839,10 @@ button.close { .panel-body:after, .modal-footer:before, .modal-footer:after { - display: table; - content: " "; + display: table; + content: " "; } + .clearfix:after, .container:after, .container-fluid:after, @@ -5634,151 +6857,188 @@ button.close { .pager:after, .panel-body:after, .modal-footer:after { - clear: both; + clear: both; } + .center-block { - display: block; - margin-right: auto; - margin-left: auto; + display: block; + margin-right: auto; + margin-left: auto; } + .pull-right { - float: right !important; + float: right !important; } + .pull-left { - float: left !important; + float: left !important; } + .hide { - display: none !important; + display: none !important; } + .show { - display: block !important; + display: block !important; } + .invisible { - visibility: hidden; + visibility: hidden; } + .text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; } + .hidden { - display: none !important; - visibility: hidden !important; + display: none !important; + visibility: hidden !important; } + .affix { - position: fixed; + position: fixed; } + @-ms-viewport { - width: device-width; + width: device-width; } + .visible-xs, .visible-sm, .visible-md, .visible-lg { - display: none !important; + display: none !important; } + @media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } + .visible-xs { + display: block !important; + } + + table.visible-xs { + display: table; + } + + tr.visible-xs { + display: table-row !important; + } + + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } } + @media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } + .visible-sm { + display: block !important; + } + + table.visible-sm { + display: table; + } + + tr.visible-sm { + display: table-row !important; + } + + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } } + @media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } + .visible-md { + display: block !important; + } + + table.visible-md { + display: table; + } + + tr.visible-md { + display: table-row !important; + } + + th.visible-md, + td.visible-md { + display: table-cell !important; + } } + @media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } + .visible-lg { + display: block !important; + } + + table.visible-lg { + display: table; + } + + tr.visible-lg { + display: table-row !important; + } + + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } } + @media (max-width: 767px) { - .hidden-xs { - display: none !important; - } + .hidden-xs { + display: none !important; + } } + @media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } + .hidden-sm { + display: none !important; + } } + @media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } + .hidden-md { + display: none !important; + } } + @media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } + .hidden-lg { + display: none !important; + } } + .visible-print { - display: none !important; + display: none !important; } + @media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } + .visible-print { + display: block !important; + } + + table.visible-print { + display: table; + } + + tr.visible-print { + display: table-row !important; + } + + th.visible-print, + td.visible-print { + display: table-cell !important; + } } + @media print { - .hidden-print { - display: none !important; - } + .hidden-print { + display: none !important; + } } \ No newline at end of file
    ').addClass('cw').text('#')); + } + + while (currentDate.isBefore(viewDate.clone().endOf('w'))) { + row.append($('').addClass('dow').text(currentDate.format('dd'))); + currentDate.add(1, 'd'); + } + widget.find('.datepicker-days thead').append(row); + }, + + isInDisabledDates = function (testDate) { + return options.disabledDates[testDate.format('YYYY-MM-DD')] === true; + }, + + isInEnabledDates = function (testDate) { + return options.enabledDates[testDate.format('YYYY-MM-DD')] === true; + }, + + isValid = function (targetMoment, granularity) { + if (!targetMoment.isValid()) { + return false; + } + if (options.disabledDates && isInDisabledDates(targetMoment)) { + return false; + } + if (options.enabledDates) { + if (isInEnabledDates(targetMoment)) { + return true; + } else { + return false; + } + } + if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) { + return false; + } + if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) { + return false; + } + if (granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { + return false; + } + return true; + }, + + fillMonths = function () { + var spans = [], + monthsShort = viewDate.clone().startOf('y').hour(12); // hour is changed to avoid DST issues in some browsers + while (monthsShort.isSame(viewDate, 'y')) { + spans.push($('').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM'))); + monthsShort.add(1, 'M'); + } + widget.find('.datepicker-months td').empty().append(spans); + }, + + updateMonths = function () { + var monthsView = widget.find('.datepicker-months'), + monthsViewHeader = monthsView.find('th'), + months = monthsView.find('tbody').find('span'); + + monthsView.find('.disabled').removeClass('disabled'); + + if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) { + monthsViewHeader.eq(0).addClass('disabled'); + } + + monthsViewHeader.eq(1).text(viewDate.year()); + + if (!isValid(viewDate.clone().add(1, 'y'), 'y')) { + monthsViewHeader.eq(2).addClass('disabled'); + } + + months.removeClass('active'); + if (date.isSame(viewDate, 'y')) { + months.eq(date.month()).addClass('active'); + } + + months.each(function (index) { + if (!isValid(viewDate.clone().month(index), 'M')) { + $(this).addClass('disabled'); + } + }); + }, + + updateYears = function () { + var yearsView = widget.find('.datepicker-years'), + yearsViewHeader = yearsView.find('th'), + startYear = viewDate.clone().subtract(5, 'y'), + endYear = viewDate.clone().add(6, 'y'), + html = ''; + + yearsView.find('.disabled').removeClass('disabled'); + + if (options.minDate && options.minDate.isAfter(startYear, 'y')) { + yearsViewHeader.eq(0).addClass('disabled'); + } + + yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year()); + + if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) { + yearsViewHeader.eq(2).addClass('disabled'); + } + + while (!startYear.isAfter(endYear, 'y')) { + html += '' + startYear.year() + ''; + startYear.add(1, 'y'); + } + + yearsView.find('td').html(html); + }, + + fillDate = function () { + var daysView = widget.find('.datepicker-days'), + daysViewHeader = daysView.find('th'), + currentDate, + html = [], + row, + clsName; + + if (!hasDate()) { + return; + } + + daysView.find('.disabled').removeClass('disabled'); + daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat)); + + if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) { + daysViewHeader.eq(0).addClass('disabled'); + } + if (!isValid(viewDate.clone().add(1, 'M'), 'M')) { + daysViewHeader.eq(2).addClass('disabled'); + } + + currentDate = viewDate.clone().startOf('M').startOf('week'); + + while (!viewDate.clone().endOf('M').endOf('w').isBefore(currentDate, 'd')) { + if (currentDate.weekday() === 0) { + row = $('
    ' + currentDate.week() + '' + currentDate.date() + '
    ' + currentHour.format(use24Hours ? 'HH' : 'hh') + '
    ' + currentMinute.format('mm') + '
    ' + currentSecond.format('ss') + '