commit eaf954ae377bbd69374f90d2645098212c286770 Author: bohung Date: Wed Jul 22 10:23:36 2020 +0800 init and finish 1st version. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de5d954 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.bundle/ +log/*.log +pkg/ +test/dummy/db/*.sqlite3 +test/dummy/db/*.sqlite3-journal +test/dummy/log/*.log +test/dummy/tmp/ +test/dummy/.sass-cache diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d15019e --- /dev/null +++ b/Gemfile @@ -0,0 +1,14 @@ +source "https://rubygems.org" + +# Declare your gem's dependencies in bulletin.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use debugger +# gem 'debugger' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..a240dc8 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,106 @@ +PATH + remote: . + specs: + announcement (0.0.1) + mongoid (= 4.0.0.beta1) + rails (~> 4.1.0.rc2) + +GEM + remote: https://rubygems.org/ + specs: + actionmailer (4.1.0.rc2) + actionpack (= 4.1.0.rc2) + actionview (= 4.1.0.rc2) + mail (~> 2.5.4) + actionpack (4.1.0.rc2) + actionview (= 4.1.0.rc2) + activesupport (= 4.1.0.rc2) + rack (~> 1.5.2) + rack-test (~> 0.6.2) + actionview (4.1.0.rc2) + activesupport (= 4.1.0.rc2) + builder (~> 3.1) + erubis (~> 2.7.0) + activemodel (4.1.0.rc2) + activesupport (= 4.1.0.rc2) + builder (~> 3.1) + activerecord (4.1.0.rc2) + activemodel (= 4.1.0.rc2) + activesupport (= 4.1.0.rc2) + arel (~> 5.0.0) + activesupport (4.1.0.rc2) + i18n (~> 0.6, >= 0.6.9) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.1) + tzinfo (~> 1.1) + arel (5.0.0) + atomic (1.1.16) + bson (2.2.1) + builder (3.2.2) + connection_pool (2.0.0) + erubis (2.7.0) + hike (1.2.3) + i18n (0.6.9) + json (1.8.1) + mail (2.5.4) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.25.1) + minitest (5.3.1) + mongoid (4.0.0.beta1) + activemodel (>= 4.0.0) + moped (~> 2.0.beta6) + origin (~> 2.1) + tzinfo (>= 0.3.37) + moped (2.0.0.rc1) + bson (~> 2.2) + connection_pool (~> 2.0) + optionable (~> 0.2.0) + multi_json (1.9.2) + optionable (0.2.0) + origin (2.1.1) + polyglot (0.3.4) + rack (1.5.2) + rack-test (0.6.2) + rack (>= 1.0) + rails (4.1.0.rc2) + actionmailer (= 4.1.0.rc2) + actionpack (= 4.1.0.rc2) + actionview (= 4.1.0.rc2) + activemodel (= 4.1.0.rc2) + activerecord (= 4.1.0.rc2) + activesupport (= 4.1.0.rc2) + bundler (>= 1.3.0, < 2.0) + railties (= 4.1.0.rc2) + sprockets-rails (~> 2.0.0) + railties (4.1.0.rc2) + actionpack (= 4.1.0.rc2) + activesupport (= 4.1.0.rc2) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (10.2.2) + sprockets (2.12.0) + hike (~> 1.2) + multi_json (~> 1.0) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + sprockets-rails (2.0.1) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (~> 2.8) + thor (0.19.1) + thread_safe (0.3.1) + atomic (>= 1.1.7, < 2) + tilt (1.4.1) + treetop (1.4.15) + polyglot + polyglot (>= 0.3.1) + tzinfo (1.1.0) + thread_safe (~> 0.1) + +PLATFORMS + ruby + +DEPENDENCIES + announcement! diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..ea966ec --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2014 YOURNAME + +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. diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..acb668e --- /dev/null +++ b/README.rdoc @@ -0,0 +1,3 @@ += Event News + +This project rocks and uses MIT-LICENSE. \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..ccd84f8 --- /dev/null +++ b/Rakefile @@ -0,0 +1,32 @@ +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Announcement' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/*.rb') +end + + + + +Bundler::GemHelper.install_tasks + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + + +task default: :test diff --git a/app/assets/images/event_news/.keep b/app/assets/images/event_news/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/javascripts/admin/event_news.js b/app/assets/javascripts/admin/event_news.js new file mode 100644 index 0000000..dee720f --- /dev/null +++ b/app/assets/javascripts/admin/event_news.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/event_news/.keep b/app/assets/javascripts/event_news/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/javascripts/form.js b/app/assets/javascripts/form.js new file mode 100644 index 0000000..6be0876 --- /dev/null +++ b/app/assets/javascripts/form.js @@ -0,0 +1,21 @@ +$(document).ready(function() { + var config = {} + config.autoGrow_minHeight = 50; + config.allowedContent = false; + config.disallowedContent = 'img'; + config.toolbar = [ + { name: 'clipboard', items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] }, + { name: 'editing', items: [ 'Find', 'Replace', '-', 'SelectAll', '-', 'Scayt' ] }, + + { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'CopyFormatting', 'RemoveFormat' ] }, + '/', + { name: 'insert', items: [ 'SpecialChar'] }, + { name: 'styles', items: [ 'Font' ] }, + { name: 'colors', items: [ 'TextColor', 'BGColor' ] } + ]; + + var ckeditor_reduce = $('.ckeditor_reduce') + ckeditor_reduce.each(function(i,v){ + CKEDITOR.replace(v,config); + }) +}); \ No newline at end of file diff --git a/app/assets/stylesheets/admin/event_news.css b/app/assets/stylesheets/admin/event_news.css new file mode 100644 index 0000000..2c22c38 --- /dev/null +++ b/app/assets/stylesheets/admin/event_news.css @@ -0,0 +1,7 @@ +/* + Place all the styles related to the matching controller here. + They will automatically be included in application.css. +*/ +.table .expired{ + color: #BE2E2E; +} \ No newline at end of file diff --git a/app/assets/stylesheets/event_news/.keep b/app/assets/stylesheets/event_news/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/stylesheets/event_news/bootstrap/_mixins.scss b/app/assets/stylesheets/event_news/bootstrap/_mixins.scss new file mode 100644 index 0000000..74ccf9f --- /dev/null +++ b/app/assets/stylesheets/event_news/bootstrap/_mixins.scss @@ -0,0 +1,947 @@ +// +// Mixins +// -------------------------------------------------- + + +// Utilities +// ------------------------- + +// Clearfix +// Source: http://nicolasgallagher.com/micro-clearfix-hack/ +// +// For modern browsers +// 1. The space content is one way to avoid an Opera bug when the +// contenteditable attribute is included anywhere else in the document. +// Otherwise it causes space to appear at the top and bottom of elements +// that are clearfixed. +// 2. The use of `table` rather than `block` is only necessary if using +// `:before` to contain the top-margins of child elements. +@mixin clearfix() { + &:before, + &:after { + content: " "; // 1 + display: table; // 2 + } + &:after { + clear: both; + } +} + +// WebKit-style focus +@mixin tab-focus() { + // Default + outline: thin dotted; + // WebKit + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +// Center-align a block level element +@mixin center-block() { + display: block; + margin-left: auto; + margin-right: auto; +} + +// Sizing shortcuts +@mixin size($width, $height) { + width: $width; + height: $height; +} +@mixin square($size) { + @include size($size, $size); +} + +// Placeholder text +@mixin placeholder($color: $input-color-placeholder) { + &::-moz-placeholder { color: $color; // Firefox + opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526 + &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+ + &::-webkit-input-placeholder { color: $color; } // Safari and Chrome +} + +// Text overflow +// Requires inline-block or block for proper styling +@mixin text-overflow() { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +// CSS image replacement +// +// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for +// mixins being reused as classes with the same name, this doesn't hold up. As +// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note +// that we cannot chain the mixins together in Less, so they are repeated. +// +// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757 + +// Deprecated as of v3.0.1 (will be removed in v4) +@mixin hide-text() { + font: #{0/0} a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +// New mixin to use as of v3.0.1 +@mixin text-hide() { + @include hide-text(); +} + + + +// CSS3 PROPERTIES +// -------------------------------------------------- + +// Single side border-radius +@mixin border-top-radius($radius) { + border-top-right-radius: $radius; + border-top-left-radius: $radius; +} +@mixin border-right-radius($radius) { + border-bottom-right-radius: $radius; + border-top-right-radius: $radius; +} +@mixin border-bottom-radius($radius) { + border-bottom-right-radius: $radius; + border-bottom-left-radius: $radius; +} +@mixin border-left-radius($radius) { + border-bottom-left-radius: $radius; + border-top-left-radius: $radius; +} + +// Drop shadows +// +// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's +// supported browsers that have box shadow capabilities now support the +// standard `box-shadow` property. +@mixin box-shadow($shadow...) { + -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1 + box-shadow: $shadow; +} + +// Transitions +@mixin transition($transition...) { + -webkit-transition: $transition; + transition: $transition; +} +@mixin transition-property($transition-property...) { + -webkit-transition-property: $transition-property; + transition-property: $transition-property; +} +@mixin transition-delay($transition-delay) { + -webkit-transition-delay: $transition-delay; + transition-delay: $transition-delay; +} +@mixin transition-duration($transition-duration...) { + -webkit-transition-duration: $transition-duration; + transition-duration: $transition-duration; +} +@mixin transition-transform($transition...) { + -webkit-transition: -webkit-transform $transition; + -moz-transition: -moz-transform $transition; + -o-transition: -o-transform $transition; + transition: transform $transition; +} + +// Transformations +@mixin rotate($degrees) { + -webkit-transform: rotate($degrees); + -ms-transform: rotate($degrees); // IE9 only + transform: rotate($degrees); +} +@mixin scale($scale-args...) { + -webkit-transform: scale($scale-args); + -ms-transform: scale($scale-args); // IE9 only + transform: scale($scale-args); +} +@mixin translate($x, $y) { + -webkit-transform: translate($x, $y); + -ms-transform: translate($x, $y); // IE9 only + transform: translate($x, $y); +} +@mixin skew($x, $y) { + -webkit-transform: skew($x, $y); + -ms-transform: skewX($x) skewY($y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+ + transform: skew($x, $y); +} +@mixin translate3d($x, $y, $z) { + -webkit-transform: translate3d($x, $y, $z); + transform: translate3d($x, $y, $z); +} + +@mixin rotateX($degrees) { + -webkit-transform: rotateX($degrees); + -ms-transform: rotateX($degrees); // IE9 only + transform: rotateX($degrees); +} +@mixin rotateY($degrees) { + -webkit-transform: rotateY($degrees); + -ms-transform: rotateY($degrees); // IE9 only + transform: rotateY($degrees); +} +@mixin perspective($perspective) { + -webkit-perspective: $perspective; + -moz-perspective: $perspective; + perspective: $perspective; +} +@mixin perspective-origin($perspective) { + -webkit-perspective-origin: $perspective; + -moz-perspective-origin: $perspective; + perspective-origin: $perspective; +} +@mixin transform-origin($origin) { + -webkit-transform-origin: $origin; + -moz-transform-origin: $origin; + -ms-transform-origin: $origin; // IE9 only + transform-origin: $origin; +} + +// Animations +@mixin animation($animation) { + -webkit-animation: $animation; + animation: $animation; +} +@mixin animation-name($name) { + -webkit-animation-name: $name; + animation-name: $name; +} +@mixin animation-duration($duration) { + -webkit-animation-duration: $duration; + animation-duration: $duration; +} +@mixin animation-timing-function($timing-function) { + -webkit-animation-timing-function: $timing-function; + animation-timing-function: $timing-function; +} +@mixin animation-delay($delay) { + -webkit-animation-delay: $delay; + animation-delay: $delay; +} +@mixin animation-iteration-count($iteration-count) { + -webkit-animation-iteration-count: $iteration-count; + animation-iteration-count: $iteration-count; +} +@mixin animation-direction($direction) { + -webkit-animation-direction: $direction; + animation-direction: $direction; +} + +// Backface visibility +// Prevent browsers from flickering when using CSS 3D transforms. +// Default value is `visible`, but can be changed to `hidden` +@mixin backface-visibility($visibility){ + -webkit-backface-visibility: $visibility; + -moz-backface-visibility: $visibility; + backface-visibility: $visibility; +} + +// Box sizing +@mixin box-sizing($boxmodel) { + -webkit-box-sizing: $boxmodel; + -moz-box-sizing: $boxmodel; + box-sizing: $boxmodel; +} + +// User select +// For selecting text on the page +@mixin user-select($select) { + -webkit-user-select: $select; + -moz-user-select: $select; + -ms-user-select: $select; // IE10+ + user-select: $select; +} + +// Resize anything +@mixin resizable($direction) { + resize: $direction; // Options: horizontal, vertical, both + overflow: auto; // Safari fix +} + +// CSS3 Content Columns +@mixin content-columns($column-count, $column-gap: $grid-gutter-width) { + -webkit-column-count: $column-count; + -moz-column-count: $column-count; + column-count: $column-count; + -webkit-column-gap: $column-gap; + -moz-column-gap: $column-gap; + column-gap: $column-gap; +} + +// Optional hyphenation +@mixin hyphens($mode: auto) { + word-wrap: break-word; + -webkit-hyphens: $mode; + -moz-hyphens: $mode; + -ms-hyphens: $mode; // IE10+ + -o-hyphens: $mode; + hyphens: $mode; +} + +// Opacity +@mixin opacity($opacity) { + opacity: $opacity; + // IE8 filter + $opacity-ie: ($opacity * 100); + filter: #{alpha(opacity=$opacity-ie)}; +} + + + +// GRADIENTS +// -------------------------------------------------- + + + +// Horizontal gradient, from left to right +// +// Creates two color stops, start and end, by specifying a color and position for each color stop. +// Color stops are not available in IE9 and below. +@mixin gradient-horizontal($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) { + background-image: -webkit-linear-gradient(left, color-stop($start-color $start-percent), color-stop($end-color $end-percent)); // Safari 5.1-6, Chrome 10+ + background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down +} + +// Vertical gradient, from top to bottom +// +// Creates two color stops, start and end, by specifying a color and position for each color stop. +// Color stops are not available in IE9 and below. +@mixin gradient-vertical($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) { + background-image: -webkit-linear-gradient(top, $start-color $start-percent, $end-color $end-percent); // Safari 5.1-6, Chrome 10+ + background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down +} + +@mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) { + background-repeat: repeat-x; + background-image: -webkit-linear-gradient($deg, $start-color, $end-color); // Safari 5.1-6, Chrome 10+ + background-image: linear-gradient($deg, $start-color, $end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+ +} +@mixin gradient-horizontal-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) { + background-image: -webkit-linear-gradient(left, $start-color, $mid-color $color-stop, $end-color); + background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color); + background-repeat: no-repeat; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down, gets no color-stop at all for proper fallback +} +@mixin gradient-vertical-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) { + background-image: -webkit-linear-gradient($start-color, $mid-color $color-stop, $end-color); + background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color); + background-repeat: no-repeat; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down, gets no color-stop at all for proper fallback +} +@mixin gradient-radial($inner-color: #555, $outer-color: #333) { + background-image: -webkit-radial-gradient(circle, $inner-color, $outer-color); + background-image: radial-gradient(circle, $inner-color, $outer-color); + background-repeat: no-repeat; +} +@mixin gradient-striped($color: rgba(255,255,255,.15), $angle: 45deg) { + background-image: -webkit-linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); + background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); +} + +// Reset filters for IE +// +// When you need to remove a gradient background, do not forget to use this to reset +// the IE filter for IE9 and below. +@mixin reset-filter() { + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} + + + +// Retina images +// +// Short retina mixin for setting background-image and -size + +@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) { + background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-1x}"), "#{$file-1x}")); + + @media + only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and ( min--moz-device-pixel-ratio: 2), + only screen and ( -o-min-device-pixel-ratio: 2/1), + only screen and ( min-device-pixel-ratio: 2), + only screen and ( min-resolution: 192dpi), + only screen and ( min-resolution: 2dppx) { + background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-2x}"), "#{$file-2x}")); + background-size: $width-1x $height-1x; + } +} + + +// Responsive image +// +// Keep images from scaling beyond the width of their parents. + +@mixin img-responsive($display: block) { + display: $display; + max-width: 100%; // Part 1: Set a maximum relative to the parent + height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching +} + + +// COMPONENT MIXINS +// -------------------------------------------------- + +// Horizontal dividers +// ------------------------- +// Dividers (basically an hr) within dropdowns and nav lists +@mixin nav-divider($color: #e5e5e5) { + height: 1px; + margin: (($line-height-computed / 2) - 1) 0; + overflow: hidden; + background-color: $color; +} + +// Panels +// ------------------------- +@mixin panel-variant($border, $heading-text-color, $heading-bg-color, $heading-border) { + border-color: $border; + + & > .panel-heading { + color: $heading-text-color; + background-color: $heading-bg-color; + border-color: $heading-border; + + + .panel-collapse .panel-body { + border-top-color: $border; + } + } + & > .panel-footer { + + .panel-collapse .panel-body { + border-bottom-color: $border; + } + } +} + +// Alerts +// ------------------------- +@mixin alert-variant($background, $border, $text-color) { + background-color: $background; + border-color: $border; + color: $text-color; + + hr { + border-top-color: darken($border, 5%); + } + .alert-link { + color: darken($text-color, 10%); + } +} + +// Tables +// ------------------------- +@mixin table-row-variant($state, $background) { + // Exact selectors below required to override `.table-striped` and prevent + // inheritance to nested tables. + .table > thead > tr, + .table > tbody > tr, + .table > tfoot > tr { + > td.#{$state}, + > th.#{$state}, + &.#{$state} > td, + &.#{$state} > th { + background-color: $background; + } + } + + // Hover states for `.table-hover` + // Note: this is not available for cells or rows within `thead` or `tfoot`. + .table-hover > tbody > tr { + > td.#{$state}:hover, + > th.#{$state}:hover, + &.#{$state}:hover > td, + &.#{$state}:hover > th { + background-color: darken($background, 5%); + } + } +} + +// List Groups +// ------------------------- +@mixin list-group-item-variant($state, $background, $color) { + .list-group-item-#{$state} { + color: $color; + background-color: $background; + + // [converter] extracted a& to a.list-group-item-#{$state} + } + + a.list-group-item-#{$state} { + color: $color; + + .list-group-item-heading { color: inherit; } + + &:hover, + &:focus { + color: $color; + background-color: darken($background, 5%); + } + &.active, + &.active:hover, + &.active:focus { + color: #fff; + background-color: $color; + border-color: $color; + } + } +} + +// Button variants +// ------------------------- +// Easily pump out default styles, as well as :hover, :focus, :active, +// and disabled options for all buttons +@mixin button-variant($color, $background, $border) { + color: $color; + background-color: $background; + border-color: $border; + + &:hover, + &:focus, + &:active, + &.active { + color: $color; + background-color: darken($background, 8%); + border-color: darken($border, 12%); + } + .open & { &.dropdown-toggle { + color: $color; + background-color: darken($background, 8%); + border-color: darken($border, 12%); + } } + &:active, + &.active { + background-image: none; + } + .open & { &.dropdown-toggle { + background-image: none; + } } + &.disabled, + &[disabled], + fieldset[disabled] & { + &, + &:hover, + &:focus, + &:active, + &.active { + background-color: $background; + border-color: $border; + } + } + + .badge { + color: $background; + background-color: $color; + } +} + +// Button sizes +// ------------------------- +@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { + padding: $padding-vertical $padding-horizontal; + font-size: $font-size; + line-height: $line-height; + border-radius: $border-radius; +} + +// Pagination +// ------------------------- +@mixin pagination-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) { + > li { + > a, + > span { + padding: $padding-vertical $padding-horizontal; + font-size: $font-size; + } + &:first-child { + > a, + > span { + @include border-left-radius($border-radius); + } + } + &:last-child { + > a, + > span { + @include border-right-radius($border-radius); + } + } + } +} + +// Labels +// ------------------------- +@mixin label-variant($color) { + background-color: $color; + &[href] { + &:hover, + &:focus { + background-color: darken($color, 10%); + } + } +} + +// Contextual backgrounds +// ------------------------- +// [converter] $parent hack +@mixin bg-variant($parent, $color) { + #{$parent} { + background-color: $color; + } + a#{$parent}:hover { + background-color: darken($color, 10%); + } +} + +// Typography +// ------------------------- +// [converter] $parent hack +@mixin text-emphasis-variant($parent, $color) { + #{$parent} { + color: $color; + } + a#{$parent}:hover { + color: darken($color, 10%); + } +} + +// Navbar vertical align +// ------------------------- +// Vertically center elements in the navbar. +// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin. +@mixin navbar-vertical-align($element-height) { + margin-top: (($navbar-height - $element-height) / 2); + margin-bottom: (($navbar-height - $element-height) / 2); +} + +// Progress bars +// ------------------------- +@mixin progress-bar-variant($color) { + background-color: $color; + .progress-striped & { + @include gradient-striped(); + } +} + +// Responsive utilities +// ------------------------- +// More easily include all the states for responsive-utilities.less. +// [converter] $parent hack +@mixin responsive-visibility($parent) { + #{$parent} { + display: block !important; + } + table#{$parent} { display: table; } + tr#{$parent} { display: table-row !important; } + th#{$parent}, + td#{$parent} { display: table-cell !important; } +} + +// [converter] $parent hack +@mixin responsive-invisibility($parent) { + #{$parent} { + display: none !important; + } +} + + +// Grid System +// ----------- + +// Centered container element +@mixin container-fixed() { + margin-right: auto; + margin-left: auto; + padding-left: ($grid-gutter-width / 2); + padding-right: ($grid-gutter-width / 2); + @include clearfix(); +} + +// Creates a wrapper for a series of columns +@mixin make-row($gutter: $grid-gutter-width) { + margin-left: ($gutter / -2); + margin-right: ($gutter / -2); + @include clearfix(); +} + +// Generate the extra small columns +@mixin make-xs-column($columns, $gutter: $grid-gutter-width) { + position: relative; + float: left; + width: percentage(($columns / $grid-columns)); + min-height: 1px; + padding-left: ($gutter / 2); + padding-right: ($gutter / 2); +} +@mixin make-xs-column-offset($columns) { + @media (min-width: $screen-xs-min) { + margin-left: percentage(($columns / $grid-columns)); + } +} +@mixin make-xs-column-push($columns) { + @media (min-width: $screen-xs-min) { + left: percentage(($columns / $grid-columns)); + } +} +@mixin make-xs-column-pull($columns) { + @media (min-width: $screen-xs-min) { + right: percentage(($columns / $grid-columns)); + } +} + + +// Generate the small columns +@mixin make-sm-column($columns, $gutter: $grid-gutter-width) { + position: relative; + min-height: 1px; + padding-left: ($gutter / 2); + padding-right: ($gutter / 2); + + @media (min-width: $screen-sm-min) { + float: left; + width: percentage(($columns / $grid-columns)); + } +} +@mixin make-sm-column-offset($columns) { + @media (min-width: $screen-sm-min) { + margin-left: percentage(($columns / $grid-columns)); + } +} +@mixin make-sm-column-push($columns) { + @media (min-width: $screen-sm-min) { + left: percentage(($columns / $grid-columns)); + } +} +@mixin make-sm-column-pull($columns) { + @media (min-width: $screen-sm-min) { + right: percentage(($columns / $grid-columns)); + } +} + + +// Generate the medium columns +@mixin make-md-column($columns, $gutter: $grid-gutter-width) { + position: relative; + min-height: 1px; + padding-left: ($gutter / 2); + padding-right: ($gutter / 2); + + @media (min-width: $screen-md-min) { + float: left; + width: percentage(($columns / $grid-columns)); + } +} +@mixin make-md-column-offset($columns) { + @media (min-width: $screen-md-min) { + margin-left: percentage(($columns / $grid-columns)); + } +} +@mixin make-md-column-push($columns) { + @media (min-width: $screen-md-min) { + left: percentage(($columns / $grid-columns)); + } +} +@mixin make-md-column-pull($columns) { + @media (min-width: $screen-md-min) { + right: percentage(($columns / $grid-columns)); + } +} + + +// Generate the large columns +@mixin make-lg-column($columns, $gutter: $grid-gutter-width) { + position: relative; + min-height: 1px; + padding-left: ($gutter / 2); + padding-right: ($gutter / 2); + + @media (min-width: $screen-lg-min) { + float: left; + width: percentage(($columns / $grid-columns)); + } +} +@mixin make-lg-column-offset($columns) { + @media (min-width: $screen-lg-min) { + margin-left: percentage(($columns / $grid-columns)); + } +} +@mixin make-lg-column-push($columns) { + @media (min-width: $screen-lg-min) { + left: percentage(($columns / $grid-columns)); + } +} +@mixin make-lg-column-pull($columns) { + @media (min-width: $screen-lg-min) { + right: percentage(($columns / $grid-columns)); + } +} + + +// Framework grid generation +// +// Used only by Bootstrap to generate the correct number of grid classes given +// any value of `$grid-columns`. + +// [converter] This is defined recursively in LESS, but Sass supports real loops +@mixin make-grid-columns() { + $list: ''; + $i: 1; + $list: ".col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}"; + @for $i from (1 + 1) through $grid-columns { + $list: "#{$list}, .col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}"; + } + #{$list} { + position: relative; + // Prevent columns from collapsing when empty + min-height: 1px; + // Inner gutter via padding + padding-left: ($grid-gutter-width / 2); + padding-right: ($grid-gutter-width / 2); + } +} + + +// [converter] This is defined recursively in LESS, but Sass supports real loops +@mixin float-grid-columns($class) { + $list: ''; + $i: 1; + $list: ".col-#{$class}-#{$i}"; + @for $i from (1 + 1) through $grid-columns { + $list: "#{$list}, .col-#{$class}-#{$i}"; + } + #{$list} { + float: left; + } +} + + +@mixin calc-grid-column($index, $class, $type) { + @if ($type == width) and ($index > 0) { + .col-#{$class}-#{$index} { + width: percentage(($index / $grid-columns)); + } + } + @if ($type == push) { + .col-#{$class}-push-#{$index} { + left: percentage(($index / $grid-columns)); + } + } + @if ($type == pull) { + .col-#{$class}-pull-#{$index} { + right: percentage(($index / $grid-columns)); + } + } + @if ($type == offset) { + .col-#{$class}-offset-#{$index} { + margin-left: percentage(($index / $grid-columns)); + } + } +} + +// [converter] This is defined recursively in LESS, but Sass supports real loops +@mixin loop-grid-columns($columns, $class, $type) { + @for $i from 0 through $columns { + @include calc-grid-column($i, $class, $type); + } +} + + +// Create grid for specific class +@mixin make-grid($class) { + @include float-grid-columns($class); + @include loop-grid-columns($grid-columns, $class, width); + @include loop-grid-columns($grid-columns, $class, pull); + @include loop-grid-columns($grid-columns, $class, push); + @include loop-grid-columns($grid-columns, $class, offset); +} + +// Form validation states +// +// Used in forms.less to generate the form validation CSS for warnings, errors, +// and successes. + +@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) { + // Color the label and help text + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline { + color: $text-color; + } + // Set the border and box shadow on specific inputs to match + .form-control { + border-color: $border-color; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work + &:focus { + border-color: darken($border-color, 10%); + $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%); + @include box-shadow($shadow); + } + } + // Set validation states also for addons + .input-group-addon { + color: $text-color; + border-color: $border-color; + background-color: $background-color; + } + // Optional feedback icon + .form-control-feedback { + color: $text-color; + } +} + +// Form control focus state +// +// Generate a customized focus state and for any input with the specified color, +// which defaults to the `$input-focus-border` variable. +// +// We highly encourage you to not customize the default value, but instead use +// this to tweak colors on an as-needed basis. This aesthetic change is based on +// WebKit's default styles, but applicable to a wider range of browsers. Its +// usability and accessibility should be taken into account with any change. +// +// Example usage: change the default blue border and shadow to white for better +// contrast against a dark gray background. + +@mixin form-control-focus($color: $input-border-focus) { + $color-rgba: rgba(red($color), green($color), blue($color), .6); + &:focus { + border-color: $color; + outline: 0; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba); + } +} + +// Form control sizing +// +// Relative text size, padding, and border-radii changes for form controls. For +// horizontal sizing, wrap controls in the predefined grid classes. `` background color +$input-bg: #fff !default; +//** `` background color +$input-bg-disabled: $gray-lighter !default; + +//** Text color for ``s +$input-color: $gray !default; +//** `` border color +$input-border: #ccc !default; +//** `` border radius +$input-border-radius: $border-radius-base !default; +//** Border color for inputs on focus +$input-border-focus: #66afe9 !default; + +//** Placeholder text color +$input-color-placeholder: $gray-light !default; + +//** Default `.form-control` height +$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default; +//** Large `.form-control` height +$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default; +//** Small `.form-control` height +$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default; + +$legend-color: $gray-dark !default; +$legend-border-color: #e5e5e5 !default; + +//** Background color for textual input addons +$input-group-addon-bg: $gray-lighter !default; +//** Border color for textual input addons +$input-group-addon-border-color: $input-border !default; + + +//== Dropdowns +// +//## Dropdown menu container and contents. + +//** Background for the dropdown menu. +$dropdown-bg: #fff !default; +//** Dropdown menu `border-color`. +$dropdown-border: rgba(0,0,0,.15) !default; +//** Dropdown menu `border-color` **for IE8**. +$dropdown-fallback-border: #ccc !default; +//** Divider color for between dropdown items. +$dropdown-divider-bg: #e5e5e5 !default; + +//** Dropdown link text color. +$dropdown-link-color: $gray-dark !default; +//** Hover color for dropdown links. +$dropdown-link-hover-color: darken($gray-dark, 5%) !default; +//** Hover background for dropdown links. +$dropdown-link-hover-bg: #f5f5f5 !default; + +//** Active dropdown menu item text color. +$dropdown-link-active-color: $component-active-color !default; +//** Active dropdown menu item background color. +$dropdown-link-active-bg: $component-active-bg !default; + +//** Disabled dropdown menu item background color. +$dropdown-link-disabled-color: $gray-light !default; + +//** Text color for headers within dropdown menus. +$dropdown-header-color: $gray-light !default; + +// Note: Deprecated $dropdown-caret-color as of v3.1.0 +$dropdown-caret-color: #000 !default; + + +//-- Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. +// +// Note: These variables are not generated into the Customizer. + +$zindex-navbar: 1000 !default; +$zindex-dropdown: 1000 !default; +$zindex-popover: 1010 !default; +$zindex-tooltip: 1030 !default; +$zindex-navbar-fixed: 1030 !default; +$zindex-modal-background: 1040 !default; +$zindex-modal: 1050 !default; + + +//== Media queries breakpoints +// +//## Define the breakpoints at which your layout will change, adapting to different screen sizes. + +// Extra small screen / phone +// Note: Deprecated $screen-xs and $screen-phone as of v3.0.1 +$screen-xs: 480px !default; +$screen-xs-min: $screen-xs !default; +$screen-phone: $screen-xs-min !default; + +// Small screen / tablet +// Note: Deprecated $screen-sm and $screen-tablet as of v3.0.1 +$screen-sm: 768px !default; +$screen-sm-min: $screen-sm !default; +$screen-tablet: $screen-sm-min !default; + +// Medium screen / desktop +// Note: Deprecated $screen-md and $screen-desktop as of v3.0.1 +$screen-md: 992px !default; +$screen-md-min: $screen-md !default; +$screen-desktop: $screen-md-min !default; + +// Large screen / wide desktop +// Note: Deprecated $screen-lg and $screen-lg-desktop as of v3.0.1 +$screen-lg: 1200px !default; +$screen-lg-min: $screen-lg !default; +$screen-lg-desktop: $screen-lg-min !default; + +// So media queries don't overlap when required, provide a maximum +$screen-xs-max: ($screen-sm-min - 1) !default; +$screen-sm-max: ($screen-md-min - 1) !default; +$screen-md-max: ($screen-lg-min - 1) !default; + + +//== Grid system +// +//## Define your custom responsive grid. + +//** Number of columns in the grid. +$grid-columns: 12 !default; +//** Padding between columns. Gets divided in half for the left and right. +$grid-gutter-width: 30px !default; +// Navbar collapse +//** Point at which the navbar becomes uncollapsed. +$grid-float-breakpoint: $screen-sm-min !default; +//** Point at which the navbar begins collapsing. +$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default; + + +//== Container sizes +// +//## Define the maximum width of `.container` for different screen sizes. + +// Small screen / tablet +$container-tablet: ((720px + $grid-gutter-width)) !default; +//** For `$screen-sm-min` and up. +$container-sm: $container-tablet !default; + +// Medium screen / desktop +$container-desktop: ((940px + $grid-gutter-width)) !default; +//** For `$screen-md-min` and up. +$container-md: $container-desktop !default; + +// Large screen / wide desktop +$container-large-desktop: ((1140px + $grid-gutter-width)) !default; +//** For `$screen-lg-min` and up. +$container-lg: $container-large-desktop !default; + + +//== Navbar +// +//## + +// Basics of a navbar +$navbar-height: 50px !default; +$navbar-margin-bottom: $line-height-computed !default; +$navbar-border-radius: $border-radius-base !default; +$navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default; +$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) !default; +$navbar-collapse-max-height: 340px !default; + +$navbar-default-color: #777 !default; +$navbar-default-bg: #f8f8f8 !default; +$navbar-default-border: darken($navbar-default-bg, 6.5%) !default; + +// Navbar links +$navbar-default-link-color: #777 !default; +$navbar-default-link-hover-color: #333 !default; +$navbar-default-link-hover-bg: transparent !default; +$navbar-default-link-active-color: #555 !default; +$navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%) !default; +$navbar-default-link-disabled-color: #ccc !default; +$navbar-default-link-disabled-bg: transparent !default; + +// Navbar brand label +$navbar-default-brand-color: $navbar-default-link-color !default; +$navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%) !default; +$navbar-default-brand-hover-bg: transparent !default; + +// Navbar toggle +$navbar-default-toggle-hover-bg: #ddd !default; +$navbar-default-toggle-icon-bar-bg: #888 !default; +$navbar-default-toggle-border-color: #ddd !default; + + +// Inverted navbar +// Reset inverted navbar basics +$navbar-inverse-color: $gray-light !default; +$navbar-inverse-bg: #222 !default; +$navbar-inverse-border: darken($navbar-inverse-bg, 10%) !default; + +// Inverted navbar links +$navbar-inverse-link-color: $gray-light !default; +$navbar-inverse-link-hover-color: #fff !default; +$navbar-inverse-link-hover-bg: transparent !default; +$navbar-inverse-link-active-color: $navbar-inverse-link-hover-color !default; +$navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%) !default; +$navbar-inverse-link-disabled-color: #444 !default; +$navbar-inverse-link-disabled-bg: transparent !default; + +// Inverted navbar brand label +$navbar-inverse-brand-color: $navbar-inverse-link-color !default; +$navbar-inverse-brand-hover-color: #fff !default; +$navbar-inverse-brand-hover-bg: transparent !default; + +// Inverted navbar toggle +$navbar-inverse-toggle-hover-bg: #333 !default; +$navbar-inverse-toggle-icon-bar-bg: #fff !default; +$navbar-inverse-toggle-border-color: #333 !default; + + +//== Navs +// +//## + +//=== Shared nav styles +$nav-link-padding: 10px 15px !default; +$nav-link-hover-bg: $gray-lighter !default; + +$nav-disabled-link-color: $gray-light !default; +$nav-disabled-link-hover-color: $gray-light !default; + +$nav-open-link-hover-color: #fff !default; + +//== Tabs +$nav-tabs-border-color: #ddd !default; + +$nav-tabs-link-hover-border-color: $gray-lighter !default; + +$nav-tabs-active-link-hover-bg: $body-bg !default; +$nav-tabs-active-link-hover-color: $gray !default; +$nav-tabs-active-link-hover-border-color: #ddd !default; + +$nav-tabs-justified-link-border-color: #ddd !default; +$nav-tabs-justified-active-link-border-color: $body-bg !default; + +//== Pills +$nav-pills-border-radius: $border-radius-base !default; +$nav-pills-active-link-hover-bg: $component-active-bg !default; +$nav-pills-active-link-hover-color: $component-active-color !default; + + +//== Pagination +// +//## + +$pagination-color: $link-color !default; +$pagination-bg: #fff !default; +$pagination-border: #ddd !default; + +$pagination-hover-color: $link-hover-color !default; +$pagination-hover-bg: $gray-lighter !default; +$pagination-hover-border: #ddd !default; + +$pagination-active-color: #fff !default; +$pagination-active-bg: $brand-primary !default; +$pagination-active-border: $brand-primary !default; + +$pagination-disabled-color: $gray-light !default; +$pagination-disabled-bg: #fff !default; +$pagination-disabled-border: #ddd !default; + + +//== Pager +// +//## + +$pager-bg: $pagination-bg !default; +$pager-border: $pagination-border !default; +$pager-border-radius: 15px !default; + +$pager-hover-bg: $pagination-hover-bg !default; + +$pager-active-bg: $pagination-active-bg !default; +$pager-active-color: $pagination-active-color !default; + +$pager-disabled-color: $pagination-disabled-color !default; + + +//== Jumbotron +// +//## + +$jumbotron-padding: 30px !default; +$jumbotron-color: inherit !default; +$jumbotron-bg: $gray-lighter !default; +$jumbotron-heading-color: inherit !default; +$jumbotron-font-size: ceil(($font-size-base * 1.5)) !default; + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +$state-success-text: #3c763d !default; +$state-success-bg: #dff0d8 !default; +$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%) !default; + +$state-info-text: #31708f !default; +$state-info-bg: #d9edf7 !default; +$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%) !default; + +$state-warning-text: #8a6d3b !default; +$state-warning-bg: #fcf8e3 !default; +$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%) !default; + +$state-danger-text: #a94442 !default; +$state-danger-bg: #f2dede !default; +$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%) !default; + + +//== Tooltips +// +//## + +//** Tooltip max width +$tooltip-max-width: 200px !default; +//** Tooltip text color +$tooltip-color: #fff !default; +//** Tooltip background color +$tooltip-bg: #000 !default; +$tooltip-opacity: .9 !default; + +//** Tooltip arrow width +$tooltip-arrow-width: 5px !default; +//** Tooltip arrow color +$tooltip-arrow-color: $tooltip-bg !default; + + +//== Popovers +// +//## + +//** Popover body background color +$popover-bg: #fff !default; +//** Popover maximum width +$popover-max-width: 276px !default; +//** Popover border color +$popover-border-color: rgba(0,0,0,.2) !default; +//** Popover fallback border color +$popover-fallback-border-color: #ccc !default; + +//** Popover title background color +$popover-title-bg: darken($popover-bg, 3%) !default; + +//** Popover arrow width +$popover-arrow-width: 10px !default; +//** Popover arrow color +$popover-arrow-color: #fff !default; + +//** Popover outer arrow width +$popover-arrow-outer-width: ($popover-arrow-width + 1) !default; +//** Popover outer arrow color +$popover-arrow-outer-color: fadein($popover-border-color, 5%) !default; +//** Popover outer arrow fallback color +$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) !default; + + +//== Labels +// +//## + +//** Default label background color +$label-default-bg: $gray-light !default; +//** Primary label background color +$label-primary-bg: $brand-primary !default; +//** Success label background color +$label-success-bg: $brand-success !default; +//** Info label background color +$label-info-bg: $brand-info !default; +//** Warning label background color +$label-warning-bg: $brand-warning !default; +//** Danger label background color +$label-danger-bg: $brand-danger !default; + +//** Default label text color +$label-color: #fff !default; +//** Default text color of a linked label +$label-link-hover-color: #fff !default; + + +//== Modals +// +//## + +//** Padding applied to the modal body +$modal-inner-padding: 20px !default; + +//** Padding applied to the modal title +$modal-title-padding: 15px !default; +//** Modal title line-height +$modal-title-line-height: $line-height-base !default; + +//** Background color of modal content area +$modal-content-bg: #fff !default; +//** Modal content border color +$modal-content-border-color: rgba(0,0,0,.2) !default; +//** Modal content border color **for IE8** +$modal-content-fallback-border-color: #999 !default; + +//** Modal backdrop background color +$modal-backdrop-bg: #000 !default; +//** Modal backdrop opacity +$modal-backdrop-opacity: .5 !default; +//** Modal header border color +$modal-header-border-color: #e5e5e5 !default; +//** Modal footer border color +$modal-footer-border-color: $modal-header-border-color !default; + +$modal-lg: 900px !default; +$modal-md: 600px !default; +$modal-sm: 300px !default; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +$alert-padding: 15px !default; +$alert-border-radius: $border-radius-base !default; +$alert-link-font-weight: bold !default; + +$alert-success-bg: $state-success-bg !default; +$alert-success-text: $state-success-text !default; +$alert-success-border: $state-success-border !default; + +$alert-info-bg: $state-info-bg !default; +$alert-info-text: $state-info-text !default; +$alert-info-border: $state-info-border !default; + +$alert-warning-bg: $state-warning-bg !default; +$alert-warning-text: $state-warning-text !default; +$alert-warning-border: $state-warning-border !default; + +$alert-danger-bg: $state-danger-bg !default; +$alert-danger-text: $state-danger-text !default; +$alert-danger-border: $state-danger-border !default; + + +//== Progress bars +// +//## + +//** Background color of the whole progress component +$progress-bg: #f5f5f5 !default; +//** Progress bar text color +$progress-bar-color: #fff !default; + +//** Default progress bar color +$progress-bar-bg: $brand-primary !default; +//** Success progress bar color +$progress-bar-success-bg: $brand-success !default; +//** Warning progress bar color +$progress-bar-warning-bg: $brand-warning !default; +//** Danger progress bar color +$progress-bar-danger-bg: $brand-danger !default; +//** Info progress bar color +$progress-bar-info-bg: $brand-info !default; + + +//== List group +// +//## + +//** Background color on `.list-group-item` +$list-group-bg: #fff !default; +//** `.list-group-item` border color +$list-group-border: #ddd !default; +//** List group border radius +$list-group-border-radius: $border-radius-base !default; + +//** Background color of single list elements on hover +$list-group-hover-bg: #f5f5f5 !default; +//** Text color of active list elements +$list-group-active-color: $component-active-color !default; +//** Background color of active list elements +$list-group-active-bg: $component-active-bg !default; +//** Border color of active list elements +$list-group-active-border: $list-group-active-bg !default; +$list-group-active-text-color: lighten($list-group-active-bg, 40%) !default; + +$list-group-link-color: #555 !default; +$list-group-link-heading-color: #333 !default; + + +//== Panels +// +//## + +$panel-bg: #fff !default; +$panel-body-padding: 15px !default; +$panel-border-radius: $border-radius-base !default; + +//** Border color for elements within panels +$panel-inner-border: #ddd !default; +$panel-footer-bg: #f5f5f5 !default; + +$panel-default-text: $gray-dark !default; +$panel-default-border: #ddd !default; +$panel-default-heading-bg: #f5f5f5 !default; + +$panel-primary-text: #fff !default; +$panel-primary-border: $brand-primary !default; +$panel-primary-heading-bg: $brand-primary !default; + +$panel-success-text: $state-success-text !default; +$panel-success-border: $state-success-border !default; +$panel-success-heading-bg: $state-success-bg !default; + +$panel-info-text: $state-info-text !default; +$panel-info-border: $state-info-border !default; +$panel-info-heading-bg: $state-info-bg !default; + +$panel-warning-text: $state-warning-text !default; +$panel-warning-border: $state-warning-border !default; +$panel-warning-heading-bg: $state-warning-bg !default; + +$panel-danger-text: $state-danger-text !default; +$panel-danger-border: $state-danger-border !default; +$panel-danger-heading-bg: $state-danger-bg !default; + + +//== Thumbnails +// +//## + +//** Padding around the thumbnail image +$thumbnail-padding: 4px !default; +//** Thumbnail background color +$thumbnail-bg: $body-bg !default; +//** Thumbnail border color +$thumbnail-border: #ddd !default; +//** Thumbnail border radius +$thumbnail-border-radius: $border-radius-base !default; + +//** Custom text color for thumbnail captions +$thumbnail-caption-color: $text-color !default; +//** Padding around the thumbnail caption +$thumbnail-caption-padding: 9px !default; + + +//== Wells +// +//## + +$well-bg: #f5f5f5 !default; +$well-border: darken($well-bg, 7%) !default; + + +//== Badges +// +//## + +$badge-color: #fff !default; +//** Linked badge text color on hover +$badge-link-hover-color: #fff !default; +$badge-bg: $gray-light !default; + +//** Badge text color in active nav link +$badge-active-color: $link-color !default; +//** Badge background color in active nav link +$badge-active-bg: #fff !default; + +$badge-font-weight: bold !default; +$badge-line-height: 1 !default; +$badge-border-radius: 10px !default; + + +//== Breadcrumbs +// +//## + +$breadcrumb-padding-vertical: 8px !default; +$breadcrumb-padding-horizontal: 15px !default; +//** Breadcrumb background color +$breadcrumb-bg: #f5f5f5 !default; +//** Breadcrumb text color +$breadcrumb-color: #ccc !default; +//** Text color of current page in the breadcrumb +$breadcrumb-active-color: $gray-light !default; +//** Textual separator for between breadcrumb elements +$breadcrumb-separator: "/" !default; + + +//== Carousel +// +//## + +$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; + +$carousel-control-color: #fff !default; +$carousel-control-width: 15% !default; +$carousel-control-opacity: .5 !default; +$carousel-control-font-size: 20px !default; + +$carousel-indicator-active-bg: #fff !default; +$carousel-indicator-border-color: #fff !default; + +$carousel-caption-color: #fff !default; + + +//== Close +// +//## + +$close-font-weight: bold !default; +$close-color: #000 !default; +$close-text-shadow: 0 1px 0 #fff !default; + + +//== Code +// +//## + +$code-color: #c7254e !default; +$code-bg: #f9f2f4 !default; + +$kbd-color: #fff !default; +$kbd-bg: #333 !default; + +$pre-bg: #f5f5f5 !default; +$pre-color: $gray-dark !default; +$pre-border-color: #ccc !default; +$pre-scrollable-max-height: 340px !default; + + +//== Type +// +//## + +//** Text muted color +$text-muted: $gray-light !default; +//** Abbreviations and acronyms border color +$abbr-border-color: $gray-light !default; +//** Headings small color +$headings-small-color: $gray-light !default; +//** Blockquote small color +$blockquote-small-color: $gray-light !default; +//** Blockquote font size +$blockquote-font-size: ($font-size-base * 1.25) !default; +//** Blockquote border color +$blockquote-border-color: $gray-lighter !default; +//** Page header border color +$page-header-border-color: $gray-lighter !default; + + +//== Miscellaneous +// +//## + +//** Horizontal line color. +$hr-border: $gray-lighter !default; + +//** Horizontal offset for forms and lists. +$component-offset-horizontal: 180px !default; diff --git a/app/assets/stylesheets/event_news/bootstrap/bootstrap.min.css b/app/assets/stylesheets/event_news/bootstrap/bootstrap.min.css new file mode 100644 index 0000000..fc564e4 --- /dev/null +++ b/app/assets/stylesheets/event_news/bootstrap/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * //*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:0.0625em dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 2.5em}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-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}fieldset{padding:.35em .625em .75em;margin:0 0.125em;border:0.0625em solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!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:""}blockquote,pre{border:0.0625em solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:0.0625em solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:0.0625em solid #ddd!important}}@font-face{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.woff2) format('woff2'),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:0.0625em;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:0.625em;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.875em;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:0.3125em auto -webkit-focus-ring-color;outline-offset:-0.125em}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:0.375em}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:0.25em;line-height:1.42857143;background-color:#fff;border:0.0625em solid #ddd;border-radius:0.25em;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:1.25em;margin-bottom:1.25em;border:0;border-top:0.0625em solid #eee}.sr-only{position:absolute;width:0.0625em;height:0.0625em;padding:0;margin:-0.0625em;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:1.25em;margin-bottom:0.625em}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:0.625em;margin-bottom:0.625em}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:2.250em}.h2,h2{font-size:1.875em}.h3,h3{font-size:1.500em}.h4,h4{font-size:1.125em}.h5,h5{font-size:0.875em}.h6,h6{font-size:0.750em}p{margin:0 0 0.625em}.lead{margin-bottom:1.25em;font-size:1em;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:1.313em}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:0.5625em;margin:2.5em 0 1.25em;border-bottom:0.0625em solid #eee}ol,ul{margin-top:0;margin-bottom:0.625em}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-0.3125em;list-style:none}.list-inline>li{display:inline-block;padding-right:0.3125em;padding-left:0.3125em}dl{margin-top:0;margin-bottom:1.25em}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:10em;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:11.25em}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:0.0625em dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0.625em 1.25em;margin:0 0 1.25em;font-size:1.094em;border-left:0.3125em solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:0.9375em;padding-left:0;text-align:right;border-right:0.3125em solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:1.25em;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:0.125em 0.25em;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:0.25em}kbd{padding:0.125em 0.25em;font-size:90%;color:#fff;background-color:#333;border-radius:0.1875em;-webkit-box-shadow:inset 0 -0.0625em 0 rgba(0,0,0,.25);box-shadow:inset 0 -0.0625em 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.0.3125em;margin:0 0 0.625em;font-size:0.813em;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:0.0625em solid #ccc;border-radius:0.25em}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:32.5em;overflow-y:scroll}.container{padding-right:0.9375em;padding-left:0.9375em;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:46.875em}}@media (min-width:990.125em){.container{width:60.625em}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:0.9375em;padding-left:0.9375em;margin-right:auto;margin-left:auto}.row{margin-right:-0.9375em;margin-left:-0.9375em}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.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-md-1,.col-md-10,.col-md-11,.col-md-12,.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-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.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-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:0.0625em;padding-right:0.9375em;padding-left:0.9375em}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{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:auto}.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:auto}.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:990.125em){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{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:auto}.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:auto}.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-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{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:auto}.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:auto}.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{background-color:transparent}caption{padding-top:0.5em;padding-bottom:0.5em;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:1.25em}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:0.5em;line-height:1.42857143;vertical-align:top;border-top:0.0625em solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:0.125em solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:0.125em solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:0.3125em}.table-bordered{border:0.0625em solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:0.0625em solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:0.125em}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:0.9375em;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:0.0625em solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:1.25em;font-size:1.313em;line-height:inherit;color:#333;border:0;border-bottom:0.0625em solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:0.3125em;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:0.25em 0 0;margin-top:0.0625em\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:0.3125em auto -webkit-focus-ring-color;outline-offset:-0.125em}output{display:block;padding-top:0.4375em;font-size:0.875em;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:30.25em;padding:0.375em 1.125em;font-size:0.875em;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:0.0625em solid #ccc;border-radius:0.25em;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075);box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-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 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.5em rgba(102,175,233,.6);box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.5em rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:30.25em}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:1.875em}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:40.375em}}.form-group{margin-bottom:0.9375em}.checkbox,.radio{position:relative;display:block;margin-top:0.625em;margin-bottom:0.625em}.checkbox label,.radio label{min-height:1.25em;padding-left:1.25em;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:0.25em\9;margin-left:-1.25em}.checkbox+.checkbox,.radio+.radio{margin-top:-0.3125em}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:1.25em;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:0.625em}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:30.25em;padding-top:0.4375em;padding-bottom:0.4375em;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:1.875em;padding:0.3125em 0.625em;font-size:0.750em;line-height:1.5;border-radius:0.1875em}select.input-sm{height:1.875em;line-height:1.875em}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:1.875em;padding:0.3125em 0.625em;font-size:0.750em;line-height:1.5;border-radius:0.1875em}.form-group-sm select.form-control{height:1.875em;line-height:1.875em}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:1.875em;min-height:30.125em;padding:0.375em 0.625em;font-size:0.750em;line-height:1.5}.input-lg{height:40.375em;padding:0.625em 10.375em;font-size:1.125em;line-height:1.3333333;border-radius:0.375em}select.input-lg{height:40.375em;line-height:40.375em}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:40.375em;padding:0.625em 10.375em;font-size:1.125em;line-height:1.3333333;border-radius:0.375em}.form-group-lg select.form-control{height:40.375em;line-height:40.375em}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:40.375em;min-height:2.375em;padding:10.0625em 10.375em;font-size:1.125em;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.0.3125em}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:30.25em;height:30.25em;line-height:30.25em;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:40.375em;height:40.375em;line-height:40.375em}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:1.875em;height:1.875em;line-height:1.875em}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075);box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.375em #67b168;box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.375em #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075);box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.375em #c0a16b;box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.375em #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075);box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.375em #ce8483;box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.075),0 0 0.375em #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:20.3125em}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:0.3125em;margin-bottom:0.625em;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 .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:0.4375em;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:1.6875em}.form-horizontal .form-group{margin-right:-0.9375em;margin-left:-0.9375em}@media (min-width:768px){.form-horizontal .control-label{padding-top:0.4375em;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:0.9375em}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:10.0625em;font-size:1.125em}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:0.375em;font-size:0.750em}}.btn{display:inline-block;padding:0.375em 1.125em;margin-bottom:0;font-size:0.875em;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:0.0625em solid transparent;border-radius:0.25em}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:0.3125em auto -webkit-focus-ring-color;outline-offset:-0.125em}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 0.1875em 0.3125em rgba(0,0,0,.125);box-shadow:inset 0 0.1875em 0.3125em rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:0.625em 10.375em;font-size:1.125em;line-height:1.3333333;border-radius:0.375em}.btn-group-sm>.btn,.btn-sm{padding:0.3125em 0.625em;font-size:0.750em;line-height:1.5;border-radius:0.1875em}.btn-group-xs>.btn,.btn-xs{padding:0.0625em 0.3125em;font-size:0.750em;line-height:1.5;border-radius:0.1875em}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:0.3125em}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:0.125em;vertical-align:middle;border-top:0.25em dashed;border-top:0.25em solid\9;border-right:0.25em solid transparent;border-left:0.25em solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10em;padding:0.3125em 0;margin:0.125em 0 0;font-size:0.875em;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:0.0625em solid #ccc;border:0.0625em solid rgba(0,0,0,.15);border-radius:0.25em;-webkit-box-shadow:0 0.375em 1.125em rgba(0,0,0,.175);box-shadow:0 0.375em 1.125em rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:0.0625em;margin:0.5625em 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:0.1875em 1.25em;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:0.1875em 1.25em;font-size:0.750em;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:0.25em dashed;border-bottom:0.25em solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:0.125em}@media (min-width:768px){.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}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-0.0625em}.btn-toolbar{margin-left:-0.3125em}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:0.3125em}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){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}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:0.5em;padding-left:0.5em}.btn-group>.btn-lg+.dropdown-toggle{padding-right:1.125em;padding-left:1.125em}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 0.1875em 0.3125em rgba(0,0,0,.125);box-shadow:inset 0 0.1875em 0.3125em rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:0.3125em 0.3125em 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 0.3125em 0.3125em}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{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:-0.0625em;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:0.25em;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:0.25em}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{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}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{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%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{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:40.375em;padding:0.625em 10.375em;font-size:1.125em;line-height:1.3333333;border-radius:0.375em}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:40.375em;line-height:40.375em}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:1.875em;padding:0.3125em 0.625em;font-size:0.750em;line-height:1.5;border-radius:0.1875em}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:1.875em;line-height:1.875em}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:0.375em 1.125em;font-size:0.875em;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:0.0625em solid #ccc;border-radius:0.25em}.input-group-addon.input-sm{padding:0.3125em 0.625em;font-size:0.750em;border-radius:0.1875em}.input-group-addon.input-lg{padding:0.625em 10.375em;font-size:1.125em;border-radius:0.375em}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-0.0625em}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-0.0625em}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-0.0625em}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:0.625em 0.9375em}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:0.0625em;margin:0.5625em 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:0.0625em solid #ddd}.nav-tabs>li{float:left;margin-bottom:-0.0625em}.nav-tabs>li>a{margin-right:0.125em;line-height:1.42857143;border:0.0625em solid transparent;border-radius:0.25em 0.25em 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:0.0625em solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:0.3125em;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{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>a{margin-right:0;border-radius:0.25em}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:0.0625em solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:0.0625em solid #ddd;border-radius:0.25em 0.25em 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:0.25em}.nav-pills>li+li{margin-left:0.125em}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:0.125em;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:0.3125em;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:0.25em}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:0.0625em solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:0.0625em solid #ddd;border-radius:0.25em 0.25em 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-0.0625em;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:3.125em;margin-bottom:1.25em;border:0.0625em solid transparent}@media (min-width:768px){.navbar{border-radius:0.25em}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:0.9375em;padding-left:0.9375em;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:0.0625em solid transparent;-webkit-box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.1);box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;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-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:32.5em}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:12.5em}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-0.9375em;margin-left:-0.9375em}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 0.0625em}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 0.0625em}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:0.0625em 0 0}.navbar-brand{float:left;height:3.125em;padding:0.9375em 0.9375em;font-size:1.125em;line-height:1.25em}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-0.9375em}}.navbar-toggle{position:relative;float:right;padding:0.5625em 0.625em;margin-top:0.5em;margin-right:0.9375em;margin-bottom:0.5em;background-color:transparent;background-image:none;border:0.0625em solid transparent;border-radius:0.25em}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:1.375em;height:0.125em;border-radius:0.0625em}.navbar-toggle .icon-bar+.icon-bar{margin-top:0.25em}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.0.3125em -0.9375em}.navbar-nav>li>a{padding-top:0.625em;padding-bottom:0.625em;line-height:1.25em}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:0.3125em 0.9375em 0.3125em 20.3125em}.navbar-nav .open .dropdown-menu>li>a{line-height:1.25em}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:0.9375em;padding-bottom:0.9375em}}.navbar-form{padding:0.625em 0.9375em;margin-top:0.5em;margin-right:-0.9375em;margin-bottom:0.5em;margin-left:-0.9375em;border-top:0.0625em solid transparent;border-bottom:0.0625em solid transparent;-webkit-box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.1),0 0.0625em 0 rgba(255,255,255,.1);box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.1),0 0.0625em 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 .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:0.3125em}.navbar-form .form-group:last-child{margin-bottom:0}}@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-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:0.25em;border-top-right-radius:0.25em;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:0.5em;margin-bottom:0.5em}.navbar-btn.btn-sm{margin-top:0.625em;margin-bottom:0.625em}.navbar-btn.btn-xs{margin-top:10.25em;margin-bottom:10.25em}.navbar-text{margin-top:0.9375em;margin-bottom:0.9375em}@media (min-width:768px){.navbar-text{float:left;margin-right:0.9375em;margin-left:0.9375em}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-0.9375em}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{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:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{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:focus,.navbar-inverse .navbar-nav>.open>a:hover{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:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:0.5em 0.9375em;margin-bottom:1.25em;list-style:none;background-color:#f5f5f5;border-radius:0.25em}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 0.3125em;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:1.25em 0;border-radius:0.25em}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:0.375em 1.125em;margin-left:-0.0625em;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:0.0625em solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:0.25em;border-bottom-left-radius:0.25em}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:0.25em;border-bottom-right-radius:0.25em}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:0.625em 10.375em;font-size:1.125em;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:0.375em;border-bottom-left-radius:0.375em}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:0.375em;border-bottom-right-radius:0.375em}.pagination-sm>li>a,.pagination-sm>li>span{padding:0.3125em 0.625em;font-size:0.750em;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:0.1875em;border-bottom-left-radius:0.1875em}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:0.1875em;border-bottom-right-radius:0.1875em}.pager{padding-left:0;margin:1.25em 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:0.3125em 10.25em;background-color:#fff;border:0.0625em solid #ddd;border-radius:0.9375em}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-0.0625em}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:0.625em;padding:0.1875em 0.4375em;font-size:0.750em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:0.625em}.badge:empty{display:none}.btn .badge{position:relative;top:-0.0625em}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:0.0625em 0.3125em}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:0.3125em}.nav-pills>li>a>.badge{margin-left:0.1875em}.jumbotron{padding-top:1.875em;padding-bottom:1.875em;margin-bottom:1.875em;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:0.9375em;font-size:1.313em;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:0.9375em;padding-left:0.9375em;border-radius:0.375em}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:3em;padding-bottom:3em}.container .jumbotron,.container-fluid .jumbotron{padding-right:3.75em;padding-left:3.75em}.jumbotron .h1,.jumbotron h1{font-size:3.938em}}.thumbnail{display:block;padding:0.25em;margin-bottom:1.25em;line-height:1.42857143;background-color:#fff;border:0.0625em solid #ddd;border-radius:0.25em;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:0.5625em;color:#333}.alert{padding:0.9375em;margin-bottom:1.25em;border:0.0625em solid transparent;border-radius:0.25em}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:0.3125em}.alert-dismissable,.alert-dismissible{padding-right:30.3125em}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-0.125em;right:-20.0625em;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:2.5em 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:2.5em 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:2.5em 0}to{background-position:0 0}}.progress{height:1.25em;margin-bottom:1.25em;overflow:hidden;background-color:#f5f5f5;border-radius:0.25em;-webkit-box-shadow:inset 0 0.0625em 0.125em rgba(0,0,0,.1);box-shadow:inset 0 0.0625em 0.125em rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:0.750em;line-height:1.25em;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -0.0625em 0 rgba(0,0,0,.15);box-shadow:inset 0 -0.0625em 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.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:-o-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);-webkit-background-size:2.5em 2.5em;background-size:2.5em 2.5em}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{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:-o-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}.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:-o-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}.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:-o-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}.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:-o-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{margin-top:0.9375em}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:625em}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:0.625em}.media-left,.media>.pull-left{padding-right:0.625em}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:0.3125em}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:1.25em}.list-group-item{position:relative;display:block;padding:0.625em 0.9375em;margin-bottom:-0.0625em;background-color:#fff;border:0.0625em solid #ddd}.list-group-item:first-child{border-top-left-radius:0.25em;border-top-right-radius:0.25em}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:0.25em;border-bottom-left-radius:0.25em}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:0.3125em}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:1.25em;background-color:#fff;border:0.0625em solid transparent;border-radius:0.25em;-webkit-box-shadow:0 0.0625em 0.0625em rgba(0,0,0,.05);box-shadow:0 0.0625em 0.0625em rgba(0,0,0,.05)}.panel-body{padding:0.9375em}.panel-heading{padding:0.625em 0.9375em;border-bottom:0.0625em solid transparent;border-top-left-radius:0.1875em;border-top-right-radius:0.1875em}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:1em;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:0.625em 0.9375em;background-color:#f5f5f5;border-top:0.0625em solid #ddd;border-bottom-right-radius:0.1875em;border-bottom-left-radius:0.1875em}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:0.0625em 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:0.1875em;border-top-right-radius:0.1875em}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:0.1875em;border-bottom-left-radius:0.1875em}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:0.9375em;padding-left:0.9375em}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:0.1875em;border-top-right-radius:0.1875em}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:0.1875em;border-top-right-radius:0.1875em}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.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 th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:0.1875em}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.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 th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:0.1875em}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:0.1875em;border-bottom-left-radius:0.1875em}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:0.1875em;border-bottom-left-radius:0.1875em}.panel>.table-responsive:last-child>.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 th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:0.1875em}.panel>.table-responsive:last-child>.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 th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:0.1875em}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:0.0625em solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:1.25em}.panel-group .panel{margin-bottom:0;border-radius:0.25em}.panel-group .panel+.panel{margin-top:0.3125em}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:0.0625em solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:0.0625em solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:1.25em;padding:10.5625em;margin-bottom:1.25em;background-color:#f5f5f5;border:0.0625em solid #e3e3e3;border-radius:0.25em;-webkit-box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.05);box-shadow:inset 0 0.0625em 0.0625em rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:20.25em;border-radius:0.375em}.well-sm{padding:0.5625em;border-radius:0.1875em}.close{float:right;font-size:1.313em;font-weight:700;line-height:1;color:#000;text-shadow:0 0.0625em 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-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%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:0.625em}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:0.0625em solid #999;border:0.0625em solid rgba(0,0,0,.2);border-radius:0.375em;outline:0;-webkit-box-shadow:0 0.1875em 0.5625em rgba(0,0,0,.5);box-shadow:0 0.1875em 0.5625em rgba(0,0,0,.5)}.modal-backdrop{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}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:0.9375em;border-bottom:0.0625em solid #e5e5e5}.modal-header .close{margin-top:-0.125em}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:0.9375em}.modal-footer{padding:0.9375em;text-align:right;border-top:0.0625em solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:0.3125em}.modal-footer .btn-group .btn+.btn{margin-left:-0.0625em}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9990.5625em;width:3.125em;height:3.125em;overflow:scroll}@media (min-width:768px){.modal-dialog{width:37.5em;margin:1.875em auto}.modal-content{-webkit-box-shadow:0 0.3125em 0.9375em rgba(0,0,0,.5);box-shadow:0 0.3125em 0.9375em rgba(0,0,0,.5)}.modal-sm{width:18.75em}}@media (min-width:990.125em){.modal-lg{width:56.25em}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.750em;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:0.3125em 0;margin-top:-0.1875em}.tooltip.right{padding:0 0.3125em;margin-left:0.1875em}.tooltip.bottom{padding:0.3125em 0;margin-top:0.1875em}.tooltip.left{padding:0 0.3125em;margin-left:-0.1875em}.tooltip-inner{max-width:12.5em;padding:0.1875em 0.5em;color:#fff;text-align:center;background-color:#000;border-radius:0.25em}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-0.3125em;border-width:0.3125em 0.3125em 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:0.3125em;bottom:0;margin-bottom:-0.3125em;border-width:0.3125em 0.3125em 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:0.3125em;margin-bottom:-0.3125em;border-width:0.3125em 0.3125em 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-0.3125em;border-width:0.3125em 0.3125em 0.3125em 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-0.3125em;border-width:0.3125em 0 0.3125em 0.3125em;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-0.3125em;border-width:0 0.3125em 0.3125em;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:0.3125em;margin-top:-0.3125em;border-width:0 0.3125em 0.3125em;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:0.3125em;margin-top:-0.3125em;border-width:0 0.3125em 0.3125em;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:270.375em;padding:0.0625em;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.875em;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:0.0625em solid #ccc;border:0.0625em solid rgba(0,0,0,.2);border-radius:0.375em;-webkit-box-shadow:0 0.3125em 0.625em rgba(0,0,0,.2);box-shadow:0 0.3125em 0.625em rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-0.625em}.popover.right{margin-left:0.625em}.popover.bottom{margin-top:0.625em}.popover.left{margin-left:-0.625em}.popover-title{padding:0.5em 10.25em;margin:0;font-size:0.875em;background-color:#f7f7f7;border-bottom:0.0625em solid #ebebeb;border-radius:0.3125em 0.3125em 0 0}.popover-content{padding:0.5625em 10.25em}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:10.0625em}.popover>.arrow:after{content:"";border-width:0.625em}.popover.top>.arrow{bottom:-10.0625em;left:50%;margin-left:-10.0625em;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:0.0625em;margin-left:-0.625em;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-10.0625em;margin-top:-10.0625em;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-0.625em;left:0.0625em;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-10.0625em;left:50%;margin-left:-10.0625em;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:0.0625em;margin-left:-0.625em;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-10.0625em;margin-top:-10.0625em;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:0.0625em;bottom:-0.625em;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:62.5em;perspective:62.5em}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:1.250em;color:#fff;text-align:center;text-shadow:0 0.0625em 0.125em rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));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,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));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:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-0.625em}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-0.625em}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-0.625em}.carousel-control .icon-next,.carousel-control .icon-prev{width:1.25em;height:1.25em;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:0.625em;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:0.625em;height:0.625em;margin:0.0625em;text-indent:-990.5625em;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:0.0625em solid #fff;border-radius:0.625em}.carousel-indicators .active{width:1.125em;height:1.125em;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:1.25em;left:15%;z-index:10;padding-top:1.25em;padding-bottom:1.25em;color:#fff;text-align:center;text-shadow:0 0.0625em 0.125em rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:1.875em;height:1.875em;margin-top:-0.9375em;font-size:1.875em}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-0.9375em}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-0.9375em}.carousel-caption{right:20%;left:20%;padding-bottom:1.875em}.carousel-indicators{bottom:1.25em}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:990.0625em){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:990.0625em){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:990.0625em){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:990.0625em){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:990.125em) and (max-width:1190.5625em){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:990.125em) and (max-width:1190.5625em){.visible-md-block{display:block!important}}@media (min-width:990.125em) and (max-width:1190.5625em){.visible-md-inline{display:inline!important}}@media (min-width:990.125em) and (max-width:1190.5625em){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:990.0625em){.hidden-sm{display:none!important}}@media (min-width:990.125em) and (max-width:1190.5625em){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/app/assets/stylesheets/template/modules/event_news.scss b/app/assets/stylesheets/template/modules/event_news.scss new file mode 100644 index 0000000..b09606b --- /dev/null +++ b/app/assets/stylesheets/template/modules/event_news.scss @@ -0,0 +1,692 @@ +@charset "utf-8"; + +@import "../initial"; + +// +// Widget +// + +// EventNews widget +// ## Gerneral styles for widgets +.w-event_news { + .w-event_news__widget-title { + @extend .unity-title; + } + + .w-event_news__list { + margin: 0; + padding: 0; + list-style: none; + } + + .w-event_news__item { + margin-bottom: 1.875em; + } + + .label { + font-size: 0.75rem; + font-weight: normal; + } + + .w-event_news__meta { + .w-event_news__status-wrap, + .w-event_news__postdate-wrap, + .w-event_news__category-wrap { + display: inline-block; + margin-right: 0.2em; + font-size: 0.8125em; + color: $theme-gray; + font-weight: normal; + } + + i { + color: $theme-gray; + } + } + + .w-event_news__subtitle { + font-size: 0.8125em; + color: $theme-gray; + } + + .w-event_news__entry-title { + margin-bottom: 0.625em; + } + + .w-event_news__title { + font-family: $sub-font; + color: $theme-color-main; + text-decoration: none; + font-size: 0.8125rem; + + &:hover { + color: darken($theme-color-main, 10%); + } + } +} + +// Widget-1 +.widget-event_news-1 { + .w-event_news__img-wrap { + height: 12.5em; + margin: 0 0 1em 0; + } + + .w-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } +} + +// Widget-2 +.widget-event_news-2 { + .w-event_news__img-wrap { + height: 12.5em; + margin: 0 0 1em 0; + } + + .w-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } +} + +// Widget-3 +.widget-event_news-3 { + .w-event_news__img-wrap { + height: 12.5em; + margin: 0 0 1em 0; + } + + .w-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } +} + +// Widget-4 +.widget-event_news-4 { + .w-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } + + .w-event_news__list > .w-event_news__item:nth-child(3n+1) { + clear: both; + } + + .w-event_news__img-wrap { + height: 12.5em; + margin: 0 0 1em 0; + } +} + +// Widget-5 +.widget-event_news-5 { + .w-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } + + .w-event_news__item { + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + padding-bottom: 1em; + margin-bottom: 1em; + } +} + +// Widget-6 +.widget-event_news-6 { + .w-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .w-event_news__entry-title { + margin: 0; + } + + .w-event_news__category-wrap, + .w-event_news__status, + .w-event_news__title, + .w-event_news__postdate-wrap { + font-size: 0.8125rem; + } + + .w-event_news__status { + display: inline-block; + } +} + +// Widget-7 +.widget-event_news-7 { + .w-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .w-event_news__entry-title { + margin: 0; + } + + .w-event_news__category-wrap, + .w-event_news__status, + .w-event_news__title, + .w-event_news__postdate-wrap { + font-size: 0.75rem; + } + + .w-event_news__status { + display: inline-block; + } +} + +// ## Gerneral styles for table widgets + +.w-event_news__postdate, +.w-event_news__category { + white-space: nowrap; +} + +// Widget-8 +// ## Table +.widget-event_news-8 { + .w-event_news__th { + color: #fff; + background: $theme-color-main; + font-size: 0.8125em; + border: none; + } + + .w-event_news__status { + display: inline-block; + font-size: 0.75rem; + } + + td { + font-size: 0.8125em; + } + + a:hover { + text-decoration: none; + } +} + +// Widget-9 +// ## Table +.widget-event_news-9 { + .w-event_news__th { + color: #fff; + background: $theme-color-main; + font-size: 0.8125em; + border: none; + } + + .w-event_news__status { + display: inline-block; + font-size: 0.75rem; + } + + td { + font-size: 0.8125em; + } + + a:hover { + text-decoration: none; + } +} + +// Widget-10 +.widget-event_news-10 { + .w-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .w-event_news__entry-title { + margin: 0; + } + + .w-event_news__postdate-wrap { + font-size: 0.8125em; + } + + .w-event_news__status { + display: inline-block; + font-size: 0.75rem; + } +} + +// Widget-11 +.widget-event_news-11 { + .w-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .w-event_news__entry-title { + margin: 0; + } + + .w-event_news__postdate-wrap { + font-size: 0.8125em; + } + + .w-event_news__status { + display: inline-block; + font-size: 0.75rem; + } +} + +// Widget-12 +// ## Table +.widget-event_news-12 { + .w-event_news__th { + color: #fff; + background: $theme-color-main; + font-size: 0.8125em; + border: none; + } + + .w-event_news__status { + display: inline-block; + font-size: 0.75rem; + } + + td { + font-size: 0.8125em; + } + + a:hover { + text-decoration: none; + } +} + +// Widget-13 +// ## Table +.widget-event_news-13 { + .w-event_news__th { + color: #fff; + background: $theme-color-main; + font-size: 0.8125em; + border: none; + } + + .w-event_news__status { + display: inline-block; + font-size: 0.75rem; + } + + td { + font-size: 0.8125em; + } + + a:hover { + text-decoration: none; + } +} + +// Widget-14 +.widget-event_news-14 { + .w-event_news__list { + padding: 0 0.9375em; + } + + .w-event_news__img-wrap { + height: 18.75em; + margin-bottom: 0.9375em; + + @media (min-width: $screen-md) { + height: 12.5em; + margin-bottom: 0; + } + } + + .w-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .w-event_news__entry-title { + margin: 0 0 0.625em 0; + + @media (min-width: $screen-md) { + margin-bottom: 0; + } + } + + .w-event_news__postdate-wrap { + font-size: 0.8125em; + } + + .w-event_news__status { + display: inline-block; + } + + .w-event_news__postdate { + font-size: 0.8125rem; + } +} + +// EventNews index +// ## General style for index pages +.i-event_news { + .i-event_news__page-title { + @extend .unity-title; + } + + .i-event_news__list { + margin: 0; + padding: 0; + list-style: none; + } + + .i-event_news__widget-title { + @extend .unity-title; + } + + .i-event_news__item { + margin-bottom: 1.875em; + } + + .i-event_news__img { + width: 100%; + max-width: 100%; + height: auto; + } + + .i-event_news__th { + color: $theme-white; + background: $theme-color-main; + font-size: 0.8125em; + border: none; + white-space: nowrap; + } + + .i-event_news__postdate, + .i-event_news__category, + .i-event_news__view-count { + white-space: nowrap; + } + + .i-event_news__status-wrap { + span { + display: inline-block; + padding: .2em .6em .3em; + + &:last-child { + margin: 0 0.3125em 0.1875em 0; + display: inline-block; + } + } + } + + td { + font-size: 0.8125rem; + } + + .i-event_news__title:hover { + text-decoration: none; + } + + .label { + font-size: 0.75rem; + font-weight: normal; + } + + .i-event_news__meta { + .i-event_news__status-wrap, + .i-event_news__postdate-wrap, + .i-event_news__category-wrap { + display: inline-block; + margin-right: 0.2em; + font-size: 0.8125em; + color: $theme-gray; + font-weight: normal; + } + + i { + color: $theme-gray; + } + } + + .i-event_news__subtitle { + font-size: 0.8125em; + color: $theme-gray; + } + + .i-event_news__entry-title { + margin-bottom: 0.625em; + } + + .i-event_news__title { + font-family: $sub-font; + color: $theme-color-main; + text-decoration: none; + font-size: 0.8125rem; + + &:hover { + color: darken($theme-color-main, 10%); + } + } +} + +// Index-1 +.index-event_news-1 {} + +// Index-5 +// Index-6 +.index-event_news-5, +.index-event_news-6 { + .i-event_news__img-wrap { + margin: 0 0 1em; + } + + .i-event_news__title { + font-family: $main-font; + font-size: 1.2rem; + line-height: 1.3; + } +} + +// Index-7 +.index-event_news-7 { + .i-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } + + .i-event_news__list > .i-event_news__item:nth-child(3n+1) { + clear: both; + } + + .i-event_news__img-wrap { + height: 12.5em; + margin: 0 0 1em 0; + } +} + +// Index-8 +.index-event_news-8 { + .i-event_news__title { + font-family: $main-font; + line-height: 1.3; + font-size: 1.2rem; + } + + .i-event_news__item { + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + padding-bottom: 1em; + margin-bottom: 1em; + } +} + +// Index-9 +// Index-10 +.index-event_news-9, +.index-event_news-10 { + .i-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .i-event_news__entry-title { + margin: 0; + } + + .i-event_news__category-wrap, + .i-event_news__status, + .i-event_news__title, + .i-event_news__postdate-wrap { + font-size: 0.8125rem; + } + + .i-event_news__status { + display: inline-block; + } +} + +// Index-11 +// Index-12 +.index-event_news-11, +.index-event_news-12 { + .i-event_news__item { + margin-bottom: 0.8em; + padding-bottom: 0.8em; + border-bottom: 0.0625em dashed lighten($theme-gray, 65%); + } + + .i-event_news__entry-title { + margin: 0; + } + + .i-event_news__postdate-wrap { + font-size: 0.8125em; + } + + .i-event_news__status { + display: inline-block; + font-size: 0.75rem; + } +} + +// Index-16 +.index-event_news-16 { + td ul { + margin: 0; + padding: 0; + list-style: none; + } +} + +// EventNews show +.s-event_news { + .s-event_news__show-title { + @extend .unity-title; + } + + .s-event_news__meta-wrap { + border-bottom: 0.0625em solid $theme-gray-light; + + @include clearfix; + + .s-event_news__meta--item { + font-size: 0.875rem; + margin-right: 1em; + margin-bottom: 0.6em; + float: left; + + i { + color: darken($theme-gray-light, 10%); + } + } + + .s-event_news__tag-wrap { + position: relative; + margin-right: 0; + padding-left: 1.6em; + clear: both; + float: none; + + i { + position: absolute; + top: 0.4375em; + left: 0; + } + } + + .s-event_news__tag-wrap { + .s-event_news__tag { + font-weight: normal; + } + } + } + + .s-event_news__post-wrap { + @include clearfix; + + margin-bottom: 2em; + } + + .s-event_news__related-wrap { + padding-top: 1em; + border-top: 0.0625em dotted $theme-gray-light; + } + + .s-event_news__related-file { + margin-bottom: 0.9375em; + } + + .s-event_news__related-file, + .s-event_news__related-link { + padding-bottom: 0.375em; + padding-left: 1.6em; + + i { + margin: 0.5em 0 0 -1.6em; + float: left; + color: darken($theme-gray-light, 10%); + } + } + + .s-event_news__related-link-list, + .s-event_news__related-file-list { + display: inline-block; + } + + .s-event_news__flie-title { + max-width: 9.375rem; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .s-event_news__social > * { + display: inline-block; + vertical-align: top; + } + + .s-event_news__social .print-button { + color: #fff; + font-size: 0.688em; + border-radius: 0.25em; + padding: 0.125em 0.375em; + background-color: $theme-color-main; + } + + .s-event_news__social .print-button:hover { + background-color: lighten($theme-color-main, 10%); + } +} \ No newline at end of file diff --git a/app/controllers/.keep b/app/controllers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/controllers/action_dispatch.rb b/app/controllers/action_dispatch.rb new file mode 100644 index 0000000..6712e9e --- /dev/null +++ b/app/controllers/action_dispatch.rb @@ -0,0 +1,7 @@ +module ActionDispatch + class Request + def original_url + original_fullpath + end + end +end \ No newline at end of file diff --git a/app/controllers/admin/event_news_controller.rb b/app/controllers/admin/event_news_controller.rb new file mode 100644 index 0000000..2c4af24 --- /dev/null +++ b/app/controllers/admin/event_news_controller.rb @@ -0,0 +1,479 @@ +# encoding: utf-8 +require 'rubyXL' +class Admin::EventNewsController < OrbitAdminController + include Admin::EventNewsHelper + before_action ->(module_app = @app_title) { set_variables module_app } + before_action :set_event_news, only: [:edit, :destroy] + before_action :load_access_level, :load_settings + + def initialize + super + @app_title = "event_news" + end + + def index + EventNews.remove_expired_status + @tags = @module_app.tags + @table_fields = [:status, :category, :title, "event_news.event_date", "event_news.start_date", "event_news.end_date", :last_modified] + @current_user = current_user + if EventNewsSetting.first.is_display_edit_only && !current_user.is_admin? && !current_user.is_manager?(@module_app) + current_user_is_sub_manager = !current_user.is_manager?(@module_app) && (current_user.is_sub_manager?(@module_app) || current_user.is_sub_manager_with_role?(@module_app)) rescue false + if current_user_is_sub_manager + @categories = current_user.approved_categories.select{|c| c.module_app_id == @module_app.id} rescue [] + @filter_fields = filter_fields(@categories, @tags) + @event_news = EventNews.where(:category_id.ne=>nil, :create_user_id=>current_user.id,:is_preview.in=>[false,nil]) + .order_by(sort) + .with_categories(filters("category")) + .with_tags(filters("tag")) + .with_status(filters("status")) + else + @event_news = EventNews.where(:category_id.ne=>nil, :uid=>nil) + @categories = @module_app.categories.enabled + @filter_fields = filter_fields(@categories, @tags) + end + else + @categories = @module_app.categories.enabled + @filter_fields = filter_fields(@categories, @tags) + @event_news = EventNews.where(:category_id.ne=>nil, :is_preview.in=>[false,nil]) + .order_by(sort) + .with_categories(filters("category")) + .with_tags(filters("tag")) + .with_status(filters("status")) + end + @event_news = search_data(@event_news,[:title]).page(params[:page]).per(10) + + if request.xhr? + render :partial => "index" + end + end + + def feed + @table_feed_fields = ["event_news.feed_name", :tags, "event_news.rssfeed", "event_news.jsonfeed"] + @feeds = EventNewsFeed.all.asc(:created_at) + + end + def generate_iframe_url + iframe_params = params.require(:iframe).permit! + uids = iframe_params['member_ids'].to_a.map{|m_id| MemberProfile.find(m_id).uid rescue nil}.select{|uid| !uid.nil?} + url_params = iframe_params.except(:member_ids) + url_params['uids'] = uids if uids != [] + render :text => '/xhr/panel/event_news/widget/sync_data?'+url_params.to_param + end + def settings + @setting = @event_news_setting + roles = Role.all + @sorted_members = roles.inject({}) do |members,role| + members_for_role = role.member_profiles.select{|m| (m.user.nil? ? false : m.user.approved)} + members[role] = members_for_role + members + end + @sorted_members['no_role'] = MemberProfile.any_in(:role_ids=>[nil,[]]).select{|m| (m.user.nil? ? false : m.user.approved)} + @unapproved_members = User.where(:approved => false).map{|u| u.member_profile} + end + + def import + end + + def excel_format + respond_to do |format| + format.xlsx { + response.headers['Content-Disposition'] = 'attachment; filename="event_news_import_format.xlsx"' + } + end + end + + def export_excel + @event_news = EventNews.where(:category_id.ne=>nil).desc(:created_at) + respond_to do |format| + format.xlsx { + response.headers['Content-Disposition'] = 'attachment; filename="event_news_export.xlsx"' + } + end + end + + def import_from_xml + download_tmp_xml params["import_xml"] + import_from_tmp_xml File.read(File.join(Rails.root, "tmp", "ann_cc_ntu.xml")) + redirect_to admin_event_news_path + end + + def import + end + + + def import_from_wp + import_from_wordpress params["import_xml"].tempfile + redirect_to admin_event_news_path + end + + def importanns + workbook = RubyXL::Parser.parse(params["import_file"].tempfile) + categories = @module_app.categories.asc(:created_at).to_a + tags = @module_app.tags.asc(:created_at).to_a + sheet = workbook[0] + if sheet.count <= 503 + sheet.each_with_index do |row, i| + next if i < 3 + v = row.cells.first.value + next if v == "" || v.nil? + import_this_event_news(row, categories, tags) + end + redirect_to admin_event_news_path + else + redirect_to admin_event_news_path(:error => "1") + end + end + + def createsettings + setting = EventNewsSetting.new(settings_params) + setting.save + redirect_to admin_event_news_settings_path + end + + def updatesettings + setting = @event_news_setting + ids = params['event_news_setting']['anns_status_settings'].to_a.collect do |i,v| + v['_id'] + end.compact + AnnsStatusSetting.where(:id.nin=>ids).destroy + setting.update_attributes(settings_params) + setting.save + redirect_to admin_event_news_settings_path + end + + def feedform + if params[:type] == "new" + @event_news_feed = EventNewsFeed.new + render :partial => "feed_form" + else params[:type] == "edit" + @event_news_feed = EventNewsFeed.find(params[:id]) + render :partial => "edit_feed_form" + end + end + + def createfeed + event_news_feed = EventNewsFeed.new(feed_params) + event_news_feed.save + feeds = EventNewsFeed.all.asc(:created_at) + render :partial => "feed", :collection => feeds + end + + def updatefeed + ann_feed = EventNewsFeed.find(params[:id]) + ann_feed.update_attributes(feed_params) + ann_feed.save + feeds = EventNewsFeed.all.asc(:created_at) + render :partial => "feed", :collection => feeds + end + + def deletefeed + ann_feed = EventNewsFeed.find(params[:id]) + ann_feed.destroy + feeds = EventNewsFeed.all.asc(:created_at) + render :partial => "feed", :collection => feeds + end + + def new + @tags = @module_app.tags + @statuses = [] + @event_news = EventNews.new + @event_news.email_sentdate = Time.now + @reach_limit = @event_news.check_status_limit(current_user,true) + if defined? Calendar + categories = user_authenticated_categories rescue ['all'] + if categories.first == "all" + @calendar_categories = CalendarType.all + else + @calendar_categories = CalendarType.where(:category_id.in => categories) rescue [] + end + end + end + + def create + bps = event_news_params + event_news = EventNews.new(bps) + if !bps['event_news_links_attributes'].nil? + bps['event_news_links_attributes'].each do |idx,link| + bps['event_news_links_attributes'].delete(idx.to_s) if link['url'].blank? + end + end + if((!EventNewsSetting.first.only_manager_can_edit_status) || (EventNewsSetting.first.only_manager_can_edit_status && (@current_user.is_admin? || @current_user.is_manager?(@module_app))) ) + if bps[:is_top] == "1" && !EventNewsSetting.check_limit_for_user(event_news.create_user_id, event_news.id) + bps[:is_top] = "0" + bps[:top_end_date] = nil + end + else + bps[:is_top] = false + bps[:is_hot] = false + bps[:is_hidden] = false + end + + # if !defined?(Calendar).nil? + # if bps[:add_to_calendar] == '0' && !bps[:event_id].blank? + # Event.find(bps[:event_id]).destroy rescue nil + # bps[:event_id] = nil + # elsif bps[:add_to_calendar] == '1' + # event = Event.find(bps[:event_id]) rescue Event.new(create_user_id: current_user.id) + # e_start = bps[:calendar_start_date].blank? ? bps[:postdate] : bps[:calendar_start_date] + # e_start = Time.now.to_datetime if e_start.blank? + # e_end = bps[:calendar_end_date].blank? ? bps[:deadline] : bps[:calendar_end_date] + # e_end = Time.now.to_datetime + 1.year if e_end.blank? + # event.update_attributes(event_news_id: event_news.id,start: e_start,end: e_end,update_user_id: current_user.id,all_day: bps[:calendar_all_day],calendar_type_id: bps[:calendar_type_id],title: bps[:title_translations][I18n.locale],note: bps[:subtitle_translations][I18n.locale]) + # bps[:event_id] = event.id + # end + # end + event_news.create_user_id = current_user.id + event_news.update_user_id = current_user.id + if EventNewsSetting.is_pro? + if user_can_approve? + event_news.approved = true + else + send_notification_mail_to_managers(event_news,"approval",I18n.locale) + end + else + event_news.approved = true + end + + event_news.save + build_email(event_news,I18n.locale) + redirect_to params['referer_url'] + end + + def approve_event_news + id = params[:id] + event_news = EventNews.find(id) + if params["approved"] == "true" + event_news.approved = true + event_news.rejected = false + event_news.reapproval = false + else + event_news.rejected = true + event_news.reapproval = false + event_news.rejection_reason = params["reason"] + send_rejection_email(event_news,I18n.locale) + end + event_news.save + redirect_to admin_event_news_path + end + + def edit + if can_edit_or_delete?(@event_news) + @reach_limit = @event_news.check_status_limit(current_user,true) + @tags = @module_app.tags + @categories = @module_app.categories.enabled + if defined? Calendar + categories = user_authenticated_categories rescue ['all'] + if categories.first == "all" + @calendar_categories = CalendarType.all + else + @calendar_categories = CalendarType.where(:category_id.in => categories) rescue [] + end + end + @statuses = [] + @event_news.email_sentdate = Time.now if @event_news.email_sent == false + else + render_401 + end + end + + def update + uid = params[:id].split('-').last + event_news = EventNews.find_by(:uid=>uid) + bps = event_news_params + bps[:tags] = bps[:tags].blank? ? [] : bps[:tags] + bps[:email_member_ids] = bps[:email_member_ids].blank? ? [] : bps[:email_member_ids] + + if !bps['event_news_links_attributes'].nil? + bps['event_news_links_attributes'].each do |idx,link| + bps['event_news_links_attributes'].delete(idx.to_s) if link['url'].blank? + end + end + if((!EventNewsSetting.first.only_manager_can_edit_status) || (EventNewsSetting.first.only_manager_can_edit_status && (@current_user.is_admin? || @current_user.is_manager?(@module_app))) ) + if bps[:is_top] == "1" && !EventNewsSetting.check_limit_for_user(event_news.create_user_id, event_news.id) + bps[:is_top] = "0" + bps[:top_end_date] = nil + end + else + bps[:is_top] = event_news.is_top + bps[:is_hot] = event_news.is_hot + bps[:is_hidden] = event_news.is_hidden + end + # if !defined?(Calendar).nil? + # if bps[:add_to_calendar] == '0' && !bps[:event_id].blank? + # Event.find(bps[:event_id]).destroy rescue nil + # bps[:event_id] = nil + # elsif bps[:add_to_calendar] == '1' + # event = Event.find(bps[:event_id]) rescue Event.new(create_user_id: current_user.id) + # e_start = bps[:calendar_start_date].blank? ? bps[:postdate] : bps[:calendar_start_date] + # e_start = Time.now.to_datetime if e_start.blank? + # e_end = bps[:calendar_end_date].blank? ? bps[:deadline] : bps[:calendar_end_date] + # e_end = Time.now.to_datetime + 1.year if e_end.blank? + # event.update_attributes(event_news_id: event_news.id,start: e_start,end: e_end,update_user_id: current_user.id,all_day: bps[:calendar_all_day],calendar_type_id: bps[:calendar_type_id],title: bps[:title_translations][I18n.locale],note: bps[:subtitle_translations][I18n.locale]) + # bps[:event_id] = event.id + # end + # end + event_news.update_attributes(bps) + event_news.update_user_id = current_user.id + if event_news.rejected + event_news.reapproval = true + event_news.save + send_notification_mail_to_managers(event_news,"reapproval",I18n.locale) + else + event_news.save + end + build_email(event_news,I18n.locale) + now_event_news_page = EventNews.where(:title.ne => "",:is_preview.in=>[false,nil]) + .order_by(sort).map(&:id).map.with_index.select{|v,i| v==event_news.id}[0][1] rescue nil + now_event_news_page = now_event_news_page.nil? ? 0 : ((now_event_news_page+1).to_f/10).ceil + redirect_to "/zh_tw/admin/event_news?page=#{now_event_news_page}" + end + + def destroy + @event_news.destroy + redirect_to "/admin/event_news" + end + + def delete + if params[:ids] + EventNews.any_in(:uid => params[:ids]).destroy_all + end + redirect_to "/admin/event_news" + end + + def preview + if params['preview_type'].eql?('edit') + event_news_data = event_news_params + org_event_news = EventNews.find(params['event_news_id']) + event_news = org_event_news.clone + event_news.generate_uid + event_news.event_news_files = [] + event_news.event_news_links = [] + if event_news_data['image'].blank? + event_news.image = org_event_news.image + end + + if !event_news_data['event_news_files_attributes'].blank? + event_news_data['event_news_files_attributes'].each do |key, event_news_file| + next if !event_news_file['_destroy'].blank? + file = nil + if event_news_file['id'].blank? + file = EventNewsFile.new(event_news_file) + file.event_news_id = event_news.id + file.save + else + org_file = EventNewsFile.find(event_news_file['id']) + file = org_file.clone + file.event_news_id = event_news.id + file.file = org_file.file + event_news_file.delete('id') + event_news_file.delete('_destroy') + file.update_attributes(event_news_file) + end + + file.save + event_news.event_news_files << file + end + end + + if !event_news_data['event_news_links_attributes'].blank? + event_news_data['event_news_links_attributes'].each do |key, event_news_link| + next if !event_news_link['_destroy'].blank? + + if event_news_link['id'].blank? + link = EventNewsLink.new(event_news_link) + link.event_news_id = event_news.id + else + link = EventNewsLink.find(event_news_link['id']).clone + link.event_news_id = event_news.id + event_news_link.delete('id') + event_news_link.delete('_destroy') + link.update_attributes(event_news_link) + end + + link.save + event_news.event_news_links << link + end + end + + event_news_data.delete('event_news_files_attributes') + event_news_data.delete('event_news_links_attributes') + event_news.update_attributes(event_news_data) + else + event_news = EventNews.new(event_news_params) + end + + event_news.is_preview = true + event_news.save + render :text=>page_for_event_news(event_news) + "?preview=true" + end + + def destroy_preview + event_news = EventNews.find_by(:uid=>params['uid']) + if event_news.is_preview + event_news.destroy + end + render :json=>{'destroy'=>event_news.id.to_s} + end + + def build_email(event_news,locale) + if event_news.email_sent and !event_news.email_addresses.blank? + if event_news.email.nil? + email = Email.new + email.save + email.deliver rescue nil + event_news.email_id = email.id + event_news.save + end + + is_sent = event_news.email.is_sent + is_sent = !params[:resend_mail].eql?("true") if !params[:resend_mail].blank? + doc = Nokogiri::HTML(event_news.title_translations[locale]) + title = doc.text.empty? ? 'no content' : doc.text + + event_news.email.update_attributes( + :create_user=>current_user, + :mail_sentdate=>event_news.email_sentdate, + :module_app=>@module_app, + :mail_lang => locale, + :mail_to=>event_news.email_addresses, + :mail_subject=>title, + :template=>'event_news/email', + :template_data=>{ + "host" => request.host_with_port, + "title" => title, + "url" => page_for_event_news(event_news) + }, + :is_sent=>is_sent + ) + event_news.email.deliver + else + event_news.email.destroy if !event_news.email.nil? + end + end + + private + + def load_settings + @event_news_setting = EventNewsSetting.first rescue nil + if @event_news_setting.nil? + @event_news_setting = EventNewsSetting.create + end + end + + def set_event_news + @event_news = EventNews.find(params[:id]) + end + + def event_news_params + params[:event_news][:email_sent] = params[:event_news][:email_sent].nil? ? 0 : params[:event_news][:email_sent] + params.require(:event_news).permit! + end + + def feed_params + params.require(:event_news_feed).permit! + end + + def settings_params + params.require(:event_news_setting).permit! + end +end diff --git a/app/controllers/event_news_controller.rb b/app/controllers/event_news_controller.rb new file mode 100644 index 0000000..63584ea --- /dev/null +++ b/app/controllers/event_news_controller.rb @@ -0,0 +1,454 @@ +class EventNewsController < ApplicationController + include EventNewsHelper + def index + EventNews.remove_expired_status + sorted,total_pages = get_sorted_event_news + event_news = sorted.collect do |a| + if a["source-site"].blank? + statuses = a.statuses_with_classname.collect do |status| + { + "status" => status["name"], + "status-class" => "status-#{status['classname']}" + } + end + locale = OrbitHelper.get_site_locale.to_s + files = a.event_news_files.map{|file| { "file_url" => file.file.url, "file_title" => (file.title.blank? ? File.basename(file.file.path) : file.title rescue '') } if file.enabled_for?(locale) } rescue [] + files.delete(nil) + links = a.event_news_links.map{|link| { "link_url" => link.url, "link_title" => (link.title.blank? ? link.url : link.title) } } rescue [] + author = User.find(a.create_user_id).member_profile.name rescue "" + desc = a.image_description + desc = (desc.blank? ? "event_news image" : desc) + link_to_show = a.is_external_link ? a.external_link : OrbitHelper.url_to_show(a.to_param) + target = a.is_external_link ? "_blank" : "_self" + doc = Nokogiri::HTML(a.title) + title = doc.text.empty? ? 'no content' : doc.text + { + "department" => author, + "event_news_links" => links, + "event_news_files" => files, + "title" => a.title, + "speaker" => a.speaker, + "host" => a.host, + "notes" => a.notes, + "source-site" => "", + "source-site-title" => "", + "source-site-link" => "", + "subtitle" => a.subtitle, + "statuses" => statuses, + "category" => a.category.title, + "postdate" => a.postdate, + "author" => author, + "is_top" => (a.is_top? ? 1 : 0), + "link_to_show" => link_to_show+"\" title=\"#{title}\"", + "target" => target, + "img_src" => a.image.thumb.url || "/assets/event_news-default.jpg", + "img_description" => desc, + "more" => t(:more_plus), + "view_count" => a.view_count + } + else + a + end + end + #If no data , hide title&table + if sorted.count == 0 + display = "hide" + end + # event_news = event_news.concat(feeds_event_news) + # total_pages = event_news.total_pages + + + { + "event_news" => event_news, + "extras" => { + "widget-title" =>t('event_news.event_news'), + "title-head" => t('event_news.table.title'), + "speaker-head" => t('event_news.speaker'), + "host-head" => t('event_news.host'), + "notes-head" => t('event_news.notes'), + "event_date-head" => t('date_'), + "date-head" => t('event_news.table.date'), + "status-head" => t('event_news.table.status'), + "author-head" => t('event_news.table.author'), + "subtitle-head" => t('event_news.table.sub_title'), + "category-head" => t('event_news.table.category'), + "link-head" => t('event_news.table.link'), + "file-head" => t('event_news.table.file'), + "view-count-head" => t('event_news.table.view_count'), + "display" => display, + "department-head" => t('event_news.table.department') + }, + "total_pages" => total_pages + } + + end + + def random_event_news_widget + pack_data(true) + end + + def widget + pack_data() + end + + def tag_cloud + ma = ModuleApp.where(:key => "event_news").first + temp = [] + ma.tags.each do |tag| + t1 = tag.taggings.collect{|t| t.taggable_id.to_s} + count = EventNews.where(:id.in => t1).can_display_and_sorted.count + temp << { + "tag-name" => tag.name, + "count" => count, + "tag-url" => OrbitHelper.widget_more_url + "?tags[]=" + tag.id.to_s + } + end + max = temp.max_by{|t| t["count"]}["count"] + tags = [] + temp.each do |tag| + if tag["count"] > 0 + percent = (tag["count"] * 100) / max + font_size = ((percent / 10).round) + 16 + tag["font-size"] = font_size + tags << tag + end + end + { + "tags" => tags, + "extras" => {} + } + end + + def pack_data(is_random=false) + tags = OrbitHelper.widget_tags || [] + cats = OrbitHelper.widget_categories || [] + subpart = OrbitHelper.get_current_widget + event_news_cache = EventNewsCache.where(parent_id: subpart.id.to_s,locale: I18n.locale.to_s) + widget_data_count = OrbitHelper.widget_data_count + set_image_version_for_widget() + devide_flag = (!(defined? SiteFeed).nil?) + if event_news_cache.count != 1 || is_random + page = Page.where(:module => "event_news").first rescue nil + EventNews.remove_expired_status + uid = OrbitHelper.params[:uid] rescue "" + sorted_event_news = EventNews.where(:title.nin => ["",nil],:is_preview.in=>[false,nil], :uid.ne => uid) + .can_display_and_sorted.is_approved + .filter_by_widget_categories(cats,false).filter_by_tags(tags) + if !is_random + sorted_event_news = sorted_event_news.limit(widget_data_count) + if event_news_cache.count > 1 + event_news_cache.destroy + end + if devide_flag + now_event_news = sorted_event_news.to_a + top_event_news = now_event_news.select{|v| v.is_top}.map{|v| data_to_human_type(v)} + not_top_event_news = now_event_news.select{|v| !v.is_top}.map{|v| data_to_human_type(v)} + EventNewsCache.create(parent_id: subpart.id.to_s,locale: I18n.locale.to_s,filter_result: {top: top_event_news,not_top: not_top_event_news}) + else + event_news = sorted_event_news.map{|v| data_to_human_type(v)} + EventNewsCache.create(parent_id: subpart.id.to_s,locale: I18n.locale.to_s,filter_result: event_news) + end + else + if devide_flag + event_news = sorted_event_news.sample(widget_data_count) + top_event_news = event_news.select{|v| v.is_top}.map{|v| data_to_human_type(v)} + not_top_event_news = event_news.select{|v| !v.is_top}.map{|v| data_to_human_type(v)} + else + event_news = sorted_event_news.sample(widget_data_count).map{|v| data_to_human_type(v)} + end + end + elsif devide_flag + now_event_news = event_news_cache.first.filter_result + top_event_news = now_event_news[:top] + not_top_event_news = now_event_news[:not_top] + else + event_news = event_news_cache.first.filter_result + end + if devide_flag + rest_count = widget_data_count - top_event_news.count + if rest_count <= 0 + event_news = top_event_news + else + feeds_event_news = get_feed_event_news("widget") + top_event_news = top_event_news + feeds_event_news.select{|v| v['is_top']} + top_event_news = top_event_news.sort{|v1,v2| v2["event_date"]<=>v1["event_date"]} + rest_all_event_news = feeds_event_news.select{|v| v['is_top'] != true} + not_top_event_news.take(rest_count) + rest_event_news = rest_all_event_news.sort{|v1,v2| v2["event_date"]<=>v1["event_date"]}.take(rest_count) + event_news = (top_event_news + rest_event_news).take(widget_data_count) + end + end + mp = (event_news[0]["img_src"] rescue "") + mpd = (event_news[0]["img_description"] rescue "") + { + "event_news" => event_news, + "extras" => { + "more_url"=>OrbitHelper.widget_more_url, + "main_picture" => mp, + "main_picture_description" => mpd, + "title-head" => t('event_news.table.title'), + "speaker-head" => t('event_news.speaker'), + "host-head" => t('event_news.host'), + "notes-head" => t('event_news.notes'), + "event_date-head" => t('date_'), + "date-head" => t('event_news.table.date'), + "author-head" => t('event_news.table.author'), + "status-head" => t('event_news.table.status'), + "subtitle-head" => t('event_news.table.sub_title'), + "category-head" => t('event_news.table.category'), + "link-head" => t('event_news.table.link'), + "file-head" => t('event_news.table.file'), + "read_more" => ("/#{I18n.locale.to_s + page.url}" rescue "") + } + } + end + + def show_local_event_news(uid, is_preview) + locale = OrbitHelper.get_site_locale.to_s + if is_preview + event_news = EventNews.where(:uid => uid).first + else + event_news = EventNews.can_display_and_sorted.where(:uid => uid).first + end + event_news = EventNews.where(:uid => uid).first if event_news.nil? + url_to_edit = OrbitHelper.user_can_edit?(event_news) ? "/admin/event_news/#{event_news.id.to_s}/edit" : "" + + access_level = OrbitHelper.user_access_level? + + if !event_news.approved && (access_level != "manager" && access_level != "admin") + if EventNewsSetting.is_pro? + if !(access_level == "sub_manager" && EventNewsSetting.first.approvers.include?(OrbitHelper.current_user.id.to_s)) + return {} + end + elsif access_level != "sub_manager" + return {} + end + end + + return {} if event_news.category.disable + + tags = event_news.tags.map{|tag| { + "tag" => tag.name , + "url" => OrbitHelper.page_for_tag(tag) + } } rescue [] + files = event_news.event_news_files.map{|file| { "file_url" => file.file.url, "file_title" => (file.title.blank? ? URI.unescape(File.basename(file.file.path)) : file.title rescue '') } if file.enabled_for?(locale) } rescue [] + files.delete(nil) + files.each do |file| + if file["file_url"] =="" || file["file_url"] == nil + files.delete(file) + end + end + links = event_news.event_news_links.map{|link| { "link_url" => link.url, "link_title" => (link.title.blank? ? link.url : link.title) } } rescue [] + update_user = event_news.update_user.member_profile.name rescue "" + desc = event_news.image_description + desc = (desc.nil? || desc == "" ? "event_news image" : desc) + + request = OrbitHelper.request + meta_desc = event_news.subtitle.nil? || event_news.subtitle == "" ? event_news.text[0..200] : event_news.subtitle + OrbitHelper.render_meta_tags([{"property" => "og:title", "content" => event_news.title},{"property" => "og:site_name", "content" => Site.first.title},{"property" => "og:url", "content" => request.original_url.split("?").first},{"property" => "og:description", "content" => meta_desc},{"property" => "og:image", "content" => "#{request.base_url}#{event_news.image.url}"},{"property" => "og:type", "content" => "Article"}]) + + subtitle_ann = nil + img_src = nil + img_description = nil + subtitle_ann = event_news.subtitle if event_news.display_subtitle? + img_src = (event_news.image.thumb.url || "/assets/event_news-default.jpg") if event_news.display_img? + img_description = event_news.image_description if (event_news.image_description.present?) && (event_news.display_img?) + + { + "tags" => tags, + "event_news_files" => files, + "event_news_links" => links, + "data" => { + "speaker-head" => t('event_news.speaker'), + "host-head" => t('event_news.host'), + "notes-head" => t('event_news.notes'), + "speaker" => event_news.speaker, + "host" => event_news.host, + "notes" => event_news.notes, + "title" => event_news.title, + "subtitle_ann" => subtitle_ann, + "update_user" => update_user, + "updated_at" => event_news.event_date.strftime('%Y-%m-%d %H:%M'), + "body" =>event_news.text, + "image" => event_news.image.url, + "img_src" => img_src, + "img_description" => img_description, + "alt_title" => desc + }, + "impressionist" => (event_news.is_preview ? nil : event_news), + "url_to_edit"=>url_to_edit + } + end + + def show_feed_event_news(uid) + event_news = OrbitHelper.get_from_feed(uid) + locale = OrbitHelper.get_site_locale.to_s + url_to_edit = "#" + return {} if event_news.blank? + tags = [] + + event_news["tags"].each{|tag| + t = Tag.where(:name => tag["name_translations"][locale]).first rescue nil + if t.nil? + I18n.locale = (locale == "en" ? :zh_tw : :en) + t = Tag.where(:name => tag["name_translations"][locale]).first rescue nil + I18n.locale = locale.to_sym + end + tags << { + "tag" => tag["name_translations"][locale], + "url" => (t.nil? ? "#" : OrbitHelper.page_for_tag(t)) + } + } + + files = event_news["event_news_files"].map{|file| { "file_url" => file["url"], "file_title" => (file["title_translations"][locale] == "" ? URI.unescape(File.basename(file["url"])) : file["title_translations"][locale] rescue '') } } rescue [] + + files.each do |file| + if file["file_url"] =="" || file["file_url"] == nil + files.delete(file) + end + end + links = event_news["event_news_links"].map{|link| { "link_url" => link["url"], "link_title" => (link["title_translations"][locale] == "" ? link["url"] : link["title_translations"][locale]) } } rescue [] + + update_user = event_news["author"] + desc = event_news["image_description_translations"][locale] rescue "" + desc = (desc.nil? || desc == "" ? "event_news image" : desc) + + request = OrbitHelper.request + if event_news["subtitle_translations"].present? + meta_desc = event_news["subtitle_translations"][locale] != "" ? event_news["subtitle_translations"][locale] : event_news["text_translations"][locale][0..200] rescue "" + else + meta_desc = "" + end + + OrbitHelper.render_meta_tags([{"property" => "og:title", "content" => event_news["title_translations"][locale]},{"property" => "og:site_name", "content" => Site.first.title},{"property" => "og:url", "content" => request.original_url.split("?").first},{"property" => "og:description", "content" => meta_desc},{"property" => "og:image", "content" => event_news["image"]["original"]},{"property" => "og:type", "content" => "Article"}]) + + datetime = DateTime.parse(event_news["event_date"]) + + { + "tags" => tags, + "event_news_files" => files, + "event_news_links" => links, + "data" => { + "speaker" => event_news["speaker"], + "host" => event_news["host"], + "notes" => event_news["notes"], + "title" => event_news["title_translations"][locale], + "update_user" => update_user, + "updated_at" => datetime.strftime('%Y-%m-%d %H:%M'), + "body" => event_news["text_translations"][locale], + "image" => event_news["image"]["original"], + "alt_title" => desc + }, + "impressionist" => nil, + "url_to_edit" => url_to_edit + } + end + + def show + params = OrbitHelper.params + uid = params[:uid] + if OrbitHelper.is_object_from_feed?(uid) + show_feed_event_news(uid) + else + show_local_event_news(uid, (params["preview"] == "true" ? true : false)) + end + end + def show_widget + @type = "show_widget" + @show_page = params[:show_page] + if params[:tags].nil? + @tags = ['all'] + else + @tags = params[:tags] + end + if params[:categories].nil? + @categories = ['all'] + else + @categories = params[:categories] + end + OrbitHelper.set_current_widget_module("event_news") + OrbitHelper.set_params(params,current_user) + EventNews.remove_expired_status + OrbitHelper.set_page_number(params[:page_no].to_i) + OrbitHelper.set_page_data_count((params[:data_count].blank? ? 10 : params[:data_count].to_i)) + sorted,total_pages = get_sorted_event_news + event_news = sorted.collect do |a| + if a["source-site"].blank? + statuses = a.statuses_with_classname.collect do |status| + { + "status" => status["name"], + "status-class" => "status-#{status['classname']}" + } + end + locale = I18n.locale.to_s + files = a.event_news_files.map{|file| { "file_url" => file.file.url, "file_title" => (file.title.blank? ? File.basename(file.file.path) : file.title rescue '') } if file.enabled_for?(locale) } rescue [] + files.delete(nil) + links = a.event_news_links.map{|link| { "link_url" => link.url, "link_title" => (link.title.blank? ? link.url : link.title) } } rescue [] + author = User.find(a.create_user_id).member_profile.name rescue "" + desc = a.image_description + desc = (desc.blank? ? "event_news image" : desc) + link_to_show = (a.is_external_link ? a.external_link : OrbitHelper.url_to_show(a.to_param)) rescue "" + target = a.is_external_link ? "_blank" : "_self" + doc = Nokogiri::HTML(a.title) + title = doc.text.empty? ? 'no content' : doc.text + { + "department" => author, + "event_news_links" => links, + "event_news_files" => files, + "title" => a.title, + "speaker" => a.speaker, + "host" => a.host, + "notes" => a.notes, + "source-site" => "", + "source-site-title" => "", + "source-site-link" => "", + "subtitle" => a.subtitle, + "statuses" => statuses, + "category" => a.category.title, + "postdate" => a.event_date, + "author" => author, + "is_top" => (a.is_top? ? 1 : 0), + "link_to_show" => link_to_show+"\" title=\"#{title}\"", + "target" => target, + "img_src" => a.image.thumb.url || "/assets/event_news-default.jpg", + "img_description" => desc, + "more" => t(:more_plus), + "view_count" => a.view_count + } + else + a + end + end + #If no data , hide title&table + if sorted.count == 0 + display = "hide" + end + # event_news = event_news.concat(feeds_event_news) + # total_pages = event_news.total_pages + + + @data = { + "event_news" => event_news, + "extras" => { + "widget-title" =>t('event_news.event_news'), + "title-head" => t('event_news.table.title'), + "speaker-head" => t('event_news.speaker'), + "host-head" => t('event_news.host'), + "notes-head" => t('event_news.notes'), + "event_date-head" => t('date_'), + "date-head" => t('event_news.table.date'), + "status-head" => t('event_news.table.status'), + "author-head" => t('event_news.table.author'), + "subtitle-head" => t('event_news.table.sub_title'), + "category-head" => t('event_news.table.category'), + "link-head" => t('event_news.table.link'), + "file-head" => t('event_news.table.file'), + "view-count-head" => t('event_news.table.view_count'), + "display" => display, + "department-head" => t('event_news.table.department') + }, + "total_pages" => total_pages + } + render :layout => false + end + +end diff --git a/app/controllers/event_news_feeds_controller.rb b/app/controllers/event_news_feeds_controller.rb new file mode 100644 index 0000000..cf92437 --- /dev/null +++ b/app/controllers/event_news_feeds_controller.rb @@ -0,0 +1,161 @@ +require "rss" +class EventNewsFeedsController < ApplicationController + include Admin::EventNewsHelper + def feed + uid = params[:uid] + anns = get_event_news(uid) + render :json => anns.to_json + end + + def rssfeed + uid = params[:uid] + @bf = EventNewsFeed.find_by(:uid => uid) rescue nil + if !@bf.nil? + tags = @bf.tag_ids + if !tags.empty? + @event_news = EventNews.can_display_and_sorted.is_approved.filter_by_tags(tags) + else + @event_news = [] + end + else + @event_news = [] + end + respond_to do |format| + format.html {redirect_to "/xhr/event_news/rssfeed/#{@bf.uid}.rss"} + format.rss + end + end + + def feeds + feeds = [] + EventNewsFeed.all.each do |bf| + feed = {} + feed["title_translations"] = bf.title_translations + feed["uid"] = bf.uid + feed["url"] = "#{request.base_url}/xhr/event_news/feed/#{bf.uid}" + feed["xml_url"] = "#{request.base_url}/xhr/event_news/rssfeed/#{bf.uid}.rss" + feed["tags"] = [] + bf.tag_ids.each do |t| + tag = Tag.find(t) + d = {} + d["name_translations"] = tag.name_translations + feed["tags"] << d + end + feeds << feed + end + render :json => {"feeds" => feeds}.to_json + end + + private + + def smart_convertor(text) + html_string = text + links = html_string.scan(/img.*?src="(.*?)"/i) + links = links + html_string.scan(/a.*?href="(.*?)"/i) + links.uniq! + links.each do |link| + l = link.first + new_link = nil + if l.starts_with?("/") + new_link = request.protocol + request.host_with_port + l + elsif l.starts_with?("..") + l1 = l.gsub("../","") + new_link = request.protocol + request.host_with_port + "/" + l1 + end + html_string = html_string.gsub(l,new_link) if !new_link.nil? + end + return html_string + end + + def get_event_news(uid) + bf = EventNewsFeed.find_by(:uid => uid) rescue nil + startdt = params[:start] + enddt = params[:end] + dt = params[:date] + if !bf.nil? + tags = bf.tag_ids + if !tags.empty? + if !dt.nil? + dt = DateTime.parse(dt) + dtt = dt + 1.day + event_news = EventNews.where(:postdate.gt => dt, :postdate.lt => dtt).can_display_and_sorted.is_approved.filter_by_tags(tags) + elsif !startdt.nil? && enddt.nil? + startdt = DateTime.parse(startdt) + enddt = DateTime.now + event_news = EventNews.where(:postdate.gt => startdt, :postdate.lt => enddt).can_display_and_sorted.is_approved.filter_by_tags(tags) + elsif !startdt.nil? && !enddt.nil? + startdt = DateTime.parse(startdt) + enddt = DateTime.parse(enddt) + 1.day + event_news = EventNews.where(:postdate.gt => startdt, :postdate.lt => enddt).can_display_and_sorted.is_approved.filter_by_tags(tags) + else + event_news = EventNews.all.can_display_and_sorted.is_approved.filter_by_tags(tags) + end + else + event_news = [] + end + end + all_anns = [] + tag_names = [] + tag_ids = [] + event_news.each do |anns| + user = User.find(anns.create_user_id) rescue nil + if !user.nil? + author = user.member_profile && user.member_profile.name == "" ? user.user_name : user.member_profile.name + else + author = "" + end + a = {} + a["id"] = anns.uid + translations_fields = ["title","subtitle","speaker","host","notes"] + translations_fields.each do |translations_field| + a[translations_field+"_translations"] = anns.send(translations_field+"_translations") + end + a["text_translations"] = {} + a["text_translations"]["en"] = smart_convertor(anns.text_translations["en"]) if !anns.text_translations["en"].blank? + a["text_translations"]["zh_tw"] = smart_convertor(anns.text_translations["zh_tw"]) if !anns.text_translations["zh_tw"].blank? + a["event_date"] = anns.event_date + a["postdate"] = anns.postdate + a["image_description_translations"] = anns.image_description_translations + a["image"] = {} + a["image"]["original"] = ("#{request.base_url}" + anns.image.url rescue "") + a["image"]["thumb"] = ("#{request.base_url}" + anns.image.thumb.url rescue "") + a["image"]["mobile"] = ("#{request.base_url}" + anns.image.mobile.url rescue "") + a["tags"] = [] + a["author"] = author + a["params"] = anns.to_param + a["event_news_links"] = [] + a["event_news_files"] = [] + anns.tags.each do |tag| + if !tag_ids.include?(tag.id.to_s) + tag_ids << tag.id.to_s + tag_names << {"name_translations" => tag.name_translations} + end + a["tags"] << {"name_translations" => tag.name_translations} + end + anns.event_news_links.each do |bl| + b = {} + b["url"] = bl.url + b["title_translations"] = bl.title_translations + a["event_news_links"] << b + end + anns.event_news_files.each do |bf| + b = {} + b["description_translations"] = bf.description_translations + b["title_translations"] = bf.title_translations + b["url"] = ("#{request.base_url}" + bf.file.url rescue "") + a["event_news_files"] << b + end + all_anns << a + end + { + "event_news" => all_anns, + "tags" => tag_names + } + end +end + + + + + + diff --git a/app/controllers/event_news_module_controller.rb b/app/controllers/event_news_module_controller.rb new file mode 100644 index 0000000..2ef6dfc --- /dev/null +++ b/app/controllers/event_news_module_controller.rb @@ -0,0 +1,129 @@ +# encoding: utf-8 +class EventNewsModuleController < ApplicationController + before_filter :set_I18n + + def get_event_news + page = Page.where(:module => "event_news").first rescue nil + + # 頁次 + page_num = params[:page_num].blank? ? 0 : params[:page_num].to_i + # 每頁顯示的則數 + per_page = params[:per_page].blank? ? 10 : params[:per_page].to_i + per_page = per_page > 0 ? per_page : 10 + + I18n.locale = :zh_tw + if !params[:keyword].blank? + keyword = Regexp.new(".*"+params[:keyword]+".*") + event_news = EventNews.any_of({:title=>keyword},{:subtitle=>keyword},{:text=>keyword}) + else + event_news = EventNews.all + end + + if !params[:category].blank? + module_id = ModuleApp.where(:key=>"event_news").first.id + category = Regexp.new(".*"+params[:category]+".*") + category_id = Category.where(:title => category, :module_app_id => module_id).first.id + event_news = event_news.where(:category_id => category_id) + else + event_news = event_news + end + + event_news = event_news.where(:is_preview.in=>[false,nil]) + event_news = event_news.where(:approved.ne => false , :rejected.ne => true) + event_news = event_news.where(:postdate.lt=>Time.now) + event_news = event_news.desc( :is_top, :postdate).page(page_num).per(per_page) + + event_news = event_news.collect do |b| + image = request.protocol + request.host_with_port + b.image.url rescue nil + + links = b.event_news_links.collect do |bl| + { + "title" => bl.title_translations, + "url" => bl.url + } + end rescue nil + + files = b.event_news_files.collect do |bf| + file = request.protocol + request.host_with_port + bf.file.url rescue nil + { + "title" => bf.title_translations, + "description" => bf.description_translations, + "file" => file + } + end rescue nil + + ts = b.tags.collect do |t| + { + "name" => t.name_translations + } + end rescue nil + + text = {"en" => "", "zh_tw" => ""} + text["en"] = (b.text_translations["en"].nil? ? "" :smart_convertor(b.text_translations["en"])) + text["zh_tw"] = (b.text_translations["zh_tw"].nil? ? "" : smart_convertor(b.text_translations["zh_tw"])) + + author = User.find(b.create_user_id).member_profile.name rescue "" + + { + "id" => b.id.to_s, + "title" => b.title_translations, + "subtitle" => b.subtitle_translations, + "text" => text, + "postdate" => b.postdate, + "deadline" => b.deadline, + "category" => b.category.title_translations, + "tags" => ts, + "image" => image, + "links" => links, + "files" => files, + "author" => author, + "url" => "/#{I18n.locale.to_s + page.url}/#{b.to_param}" + } + + end + + # 計算總筆數 Start + if !params[:keyword].blank? + keyword = Regexp.new(".*"+params[:keyword]+".*") + event_news = EventNews.any_of({:title=>keyword},{:subtitle=>keyword},{:text=>keyword}) + else + event_news = EventNews.all + end + event_news = event_news.where(:is_preview.in=>[false,nil]) + event_news = event_news.where(:approved.ne => false , :rejected.ne => true) + event_news = event_news.where(:postdate.lt=>Time.now) + total_pages = event_news.count + # End + + render :json => { + "event_news" => event_news, + "event_news_count" => event_news.count, + "page_num" => page_num, + "total_pages" => total_pages, + }.to_json + end + + def smart_convertor(text) + html_string = text + links = html_string.scan(/img.*?src="(.*?)"/i) + links.each do |link| + l = link.first + new_link = nil + if l.starts_with?("/") + new_link = request.protocol + request.host_with_port + l + elsif l.starts_with?("..") + l1 = l.gsub("../","") + new_link = request.protocol + request.host_with_port + "/" + l1 + end + html_string = html_string.sub(l,new_link) if !new_link.nil? + end + return html_string + end + + protected + + def set_I18n + I18n.locale = params[:lang] if params[:lang].present? + end + +end diff --git a/app/helpers/.keep b/app/helpers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/helpers/admin/event_news_helper.rb b/app/helpers/admin/event_news_helper.rb new file mode 100644 index 0000000..9759cf9 --- /dev/null +++ b/app/helpers/admin/event_news_helper.rb @@ -0,0 +1,320 @@ +require "net/http" +require "uri" +require 'json' + +module Admin::EventNewsHelper + def page_for_event_news(event_news) + ann_page = nil + pages = Page.where(:module=>'event_news') + + pages.each do |page| + if page.categories.count ==1 + if page.categories.include?(event_news.category.id.to_s) + ann_page = page + end + end + break if !ann_page.nil? + end + + if ann_page.nil? + pages.each do |page| + if page.categories.include?(event_news.category.id.to_s) + ann_page = page + end + break if !ann_page.nil? + end + end + + ann_page = pages.first if ann_page.nil? + request.protocol+(request.host_with_port+ann_page.url+'/'+event_news.to_param).gsub('//','/') rescue "/" + end + + def import_this_event_news(row,categories,tags) + value = {} + anns = EventNews.new + row.cells.each_with_index do |cell,index| + next if cell.nil? + val = cell.value + next if val.nil? || val == "" + case index + when 0 + anns.category = categories[val.to_i] + when 1 + new_tags = [] + if (val.include?(",") rescue false) + ts = val.split(",") + ts.each do |t| + new_tags << tags[t.to_i] + end + else + new_tags << tags[val.to_i] + end + anns.tags=new_tags + when 2 + anns.event_date = val + when 3 + anns.postdate = val + when 4 + anns.deadline = val + when 5 + anns.is_top = (val.to_i == 1 ? true : false) + when 6 + anns.is_hot = (val.to_i == 1 ? true : false) + when 7 + anns.is_hidden = (val.to_i == 1 ? true : false) + when 8 + anns.remote_image_url = val + when 9 + value["en"] = val + when 10 + value["zh_tw"] = val + anns.image_description_translations = value + value = {} + when 11 + value["en"] = val + when 12 + value["zh_tw"] = val + anns.title_translations = value + value = {} + when 13 + value["en"] = val + when 14 + value["zh_tw"] = val + anns.speaker_translations = value + value = {} + when 15 + value["en"] = val + when 16 + value["zh_tw"] = val + anns.host_translations = value + value = {} + when 17 + value["en"] = val + when 18 + value["zh_tw"] = val + anns.subtitle_translations = value + value = {} + when 19 + value["en"] = val + when 20 + value["zh_tw"] = val + anns.text_translations = value + value = {} + when 21 + value["en"] = val + when 22 + value["zh_tw"] = val + anns.notes_translations = value + value = {} + when 23 + links = val.split(";") rescue [] + desc_en = row.cells[24].value.split(";") rescue [] + desc_zh_tw = row.cells[25].value.split(";") rescue [] + links.each_with_index do |link,i| + bl = EventNewsLink.new + bl.url = link.strip + bl.title_translations = {"en" => desc_en[i], "zh_tw" => desc_zh_tw[i]} + bl.event_news_id = anns.id + bl.save + end + when 26 + files = val.split(";") rescue [] + desc_en = row.cells[27].value.split(";") rescue [] + desc_zh_tw = row.cells[28].value.split(";") rescue [] + alt_en = row.cells[29].value.split(";") rescue [] + alt_zh_tw = row.cells[30].value.split(";") rescue [] + files.each_with_index do |file, i| + bf = EventNewsFile.new + bf.remote_file_url = file.strip rescue nil + bf.title_translations = {"en" => (desc_en[i] rescue ""), "zh_tw" => (desc_zh_tw[i] rescue "")} + bf.description_translations = {"en" => (alt_en[i] rescue ""), "zh_tw" => (alt_zh_tw[i] rescue "")} + bf.event_news_id = anns.id + bf.save + end + end + end + anns.create_user_id = current_user.id.to_s + anns.update_user_id = current_user.id.to_s + anns.approved = true + anns.save + end + + def send_rejection_email(event_news,locale) + user = User.find(event_news.create_user_id) rescue nil + if !user.nil? + email = user.member_profile.email + if !email.nil? && email != "" + url = "http://#{request.host_with_port}/admin/event_news/#{event_news.id}/edit" + datatosend = "

Hello #{user.name},

#{current_user.name} #{t("event_news.rejected_event_news")} : #{event_news.rejection_reason} #{t("event_news.click_here_to_see")}

" + mail = Email.new(:mail_to => email, :mail_subject => "EventNews rejected公告未通過 : #{event_news.title_translations[locale]}.", :template => "email/event_news_email.html.erb", :template_data => {"html" => datatosend}) + mail.save + mail.deliver rescue nil + end + end + end + + def send_notification_mail_to_managers(event_news, type, locale) + users = [] + if @event_news_setting.email_to.include?("managers") + authorizations = Authorization.where(:module_app_id => @module_app.id) + users = authorizations.collect do |auth| + auth.user + end + end + if @event_news_setting.email_to.include?("admins") + wg = Workgroup.where(:key => "admin").first + admins = User.where(:workgroup_id => wg.id) + users.delete(nil) + users = users.concat(admins.to_a) + end + if @event_news_setting.email_to.include?("approvers") + approvers = User.find(@event_news_setting.approvers).to_a rescue [] + auths = Authorization.where(:category_id => event_news.category_id).collect{|a| a.user} + users = users.concat(approvers & auths) + end + users.each do |user| + email = user.member_profile.email + if !email.nil? && email != "" + send_email(user.name, email, event_news, type, locale) + # sleep(1) + end + end + end + + def send_email(name, useremail, event_news, type, locale) + url = "http://#{request.host_with_port}/admin/event_news?url=#{page_for_event_news(event_news).sub("http://" + request.host_with_port, "")}&id=#{event_news.id}" + + case type + when "approval" + datatosend = "

#{t("event_news.approval_mail_hi", :name => name)},

#{t("event_news.submitted_new_event_news", :poster => current_user.name)}

#{t("event_news.approval_event_news_title")} : #{event_news.title_translations[locale]}
#{t("event_news.click_here_to_see")} : #{url}

" + when "reapproval" + datatosend = "

#{t("event_news.approval_mail_hi", :name => name)},

#{t("event_news.updated_event_news", :poster => current_user.name)}

#{t("event_news.approval_event_news_title")} : #{event_news.title_translations[locale]}
#{t("event_news.click_here_to_see")} : #{url}

" + end + email = Email.new(:mail_to => useremail, :mail_subject => " #{t("event_news.event_news_subject")} : #{event_news.title_translations[locale]}.", :template => "email/event_news_email.html.erb", :template_data => {"html" => datatosend}) + email.save + email.deliver rescue nil + end + + def download_tmp_xml(url) + xml = File.join(Rails.root, "tmp", "ann_cc_ntu.xml") + open(xml, 'wb') do |fo| + fo.print open(url).read + end + end + + def import_from_tmp_xml(file) + xml = Nokogiri::XML(file) + return if xml.nil? + event_news = [] + xml.xpath("//channel").xpath("//item").each do |anns| + event_news << { + :title => (anns>"title").text, + :category => (anns>"category").text, + :postdate => (anns>"pubDate").text, + :text => (anns>"description").text, + :rss2_sn => (anns>"link").text.split("=").last + } + end + event_news.each do |anns| + ma = ModuleApp.where(:key => "event_news").first + cat = Category.where(:title => anns[:category]).first rescue nil + if cat.nil? + cat = Category.create(:title_translations => {"en" => anns[:category], "zh_tw" => anns[:category]}, :module_app_id => ma.id) + end + ann = EventNews.where(:rss2_sn => anns[:rss2_sn]).first rescue nil + if ann.nil? + ann = EventNews.new(:title_translations => {"en" => "", "zh_tw" => anns[:title]}, :postdate => anns[:postdate], :subtitle_translations => {"en" => "", "zh_tw" => anns[:title]}, :text_translations => {"en" => "", "zh_tw" => anns[:text]}, :rss2_sn => anns[:rss2_sn], :category_id => cat.id, :approved => true, :create_user_id => current_user.id) + else + ann.update_attributes(:title_translations => {"en" => "", "zh_tw" => anns[:title]}, :postdate => anns[:postdate], :subtitle_translations => {"en" => "", "zh_tw" => anns[:title]}, :text_translations => {"en" => "", "zh_tw" => anns[:text]}) + end + ann.save + end + File.delete(file) + end + + def import_from_wordpress(xmlfile) + xml_file = File.read(xmlfile) + doc = Nokogiri::XML.parse(xml_file) + + doc.xpath("//channel").each do|channel_data| + channel_data.xpath('//item').each do|itme| + + bu = EventNews.where(:rss2_sn => itme.xpath('wp:post_id').text ).first rescue nil + if bu.nil? + bu = EventNews.new + bu.approved = true + bu.rss2_sn = itme.xpath('wp:post_id').text + bu.title_translations = {"en" => itme.xpath('title').text, "zh_tw" => itme.xpath('title').text} + bu.text_translations = {"en" => itme.xpath('content:encoded').text, "zh_tw" => itme.xpath('content:encoded').text} + bu.postdate = itme.xpath('wp:post_date').text + + itme.xpath('category').each do |i_cate| + if i_cate["domain"].to_s == "category" + + cat = @module_app.categories.where(:title => i_cate.text.to_s).first rescue nil + if cat.nil? + cat = Category.new + cat.module_app = @module_app + cat.title_translations = {"en" => i_cate.text.to_s, "zh_tw" => i_cate.text.to_s} + cat.save + end + bu.category = cat + + elsif i_cate["domain"].to_s == "post_tag" + + tag = Tag.where(:name => i_cate.text.to_s ).first rescue nil + if tag.nil? + tag = Tag.new + tag.name_translations = {"en" => i_cate.text.to_s, "zh_tw" => i_cate.text.to_s} + tag.module_app_ids << @module_app.id + tag.save + end + + bu.tags = tag + end + end + + bu.save + end + + end + end + File.delete(xmlfile) + end + + def load_access_level + if (current_user.is_admin? rescue false) + @access_level = "admin" + elsif (current_user.is_manager?(@module_app) rescue false) + @access_level = "manager" + else + @access_level = "users" + end + end + + def user_can_approve?(anns=nil) + can_approve = false + setting = EventNewsSetting.first + case @access_level + when "admin" + can_approve = true + when "manager" + can_approve = true + else + can_approve = false + end + if !can_approve + if !anns.nil? + if setting.approvers.include?(current_user.id.to_s) + if (current_user.approved_categories_for_module(@module_app).include?(anns.category) rescue false) + can_approve = true + end + end + else + can_approve = setting.approvers.include?(current_user.id.to_s) + end + end + can_approve + end + +end diff --git a/app/helpers/event_news_helper.rb b/app/helpers/event_news_helper.rb new file mode 100644 index 0000000..c846a4b --- /dev/null +++ b/app/helpers/event_news_helper.rb @@ -0,0 +1,449 @@ +module EventNewsHelper + def set_image_version_for_widget + subpart = OrbitHelper.get_current_widget + @image_version = 'thumb' + if subpart.methods.include? 'select_options'.to_sym + ModuleApp.all.select{|tmp| tmp.key.to_s=='event_news'}.each do |modile_app| + @show_options = modile_app.show_options rescue nil + end + subpart.select_options.each do |select_option| + if !(@show_options.nil?) && select_option.field_name == @show_options.keys.first.to_s + value = YAML.load(select_option.value) + tmp = value[:en] + I18n.with_locale(:en) do + if tmp == t('event_news.small_size') + @image_version = 'thumb' + elsif tmp == t('event_news.medium_size') + @image_version = 'mobile' + elsif tmp == t('event_news.orignal_size') + @image_version = 'orignal' + end + end + end + end + end + end + def data_to_human_type(a) + statuses = a.statuses_with_classname.collect do |status| + { + "status" => status["name"], + "status-class" => "status-#{status['classname']}" + } + end + files = a.event_news_files.map{|file| { "file_url" => file.file.url, "file_title" => (file.title.blank? ? File.basename(file.file.path) : file.title rescue '') } if file.enabled_for?(locale) } rescue [] + files.delete(nil) + links = a.event_news_links.map{|link| { "link_url" => link.url, "link_title" => (link.title.blank? ? link.url : link.title) } } rescue [] + author = User.find(a.create_user_id).member_profile.name rescue "" + desc = a.image_description + desc = (desc.nil? || desc == "" ? "event_news image" : desc) + link_to_show = (a.is_external_link? ? a.external_link : OrbitHelper.widget_item_url(a.to_param)) rescue "" + target = a.is_external_link ? "_blank" : "_self" + if @image_version == 'thumb' + image_url = a.image.thumb.url + elsif @image_version == 'mobile' + image_url = a.image.mobile.url + else + image_url = a.image.url + end + { + "event_news_links" => links, + "event_news_files" => files, + "title" => a.title, + "speaker" => a.speaker, + "host" => a.host, + "notes" => a.notes, + "source-site" => "", + "source-site-title" => "", + "source-site-link" => "", + "subtitle" => a.subtitle, + "statuses" => statuses, + "category" => a.category.title, + "postdate" => a.event_date, + "author" => author, + "link_to_show" => link_to_show, + "target" => target, + "img_src" => image_url || "/assets/event_news-default.jpg", + "img_description" => desc + } + end + def get_feed_annc(type,site_source,locale) + ma_key = 'event_news' + if type == "index" + categories = Array(OrbitHelper.page_categories) + elsif type == "widget" + categories = Array(OrbitHelper.widget_categories) + else + categories = [] + end + if categories.include?("all") + feeds = SiteFeedAnnc.where(:channel_key => ma_key) + else + feeds = SiteFeedAnnc.where(:channel_key => ma_key, :merge_with_category.in => categories) + end + if feeds.count > 0 + temp_ids = [] + data = feeds.collect do |feed| + feed.all_contents_for_feed(site_source,locale,type=='widget') + end.flatten.compact + else + data = [] + end + data + end + def get_feed_event_news(type,site_source=nil) + locale = OrbitHelper.get_site_locale.to_s + if !(defined? SiteFeedAnnc).nil? + fans = get_feed_annc(type,site_source,locale) + else + feed_anns = OrbitHelper.get_feed_for_module(type) + fans = [] + feed_anns.each do |fa| + next if !site_source.nil? && site_source != fa["source-site-title"] + status = { + "status" => "#{fa["source-site-title"]}", + "status-class" => "status-source" + } + + files = fa["event_news_files"].collect{|bf| { "file_url" => bf["url"], "file_title" => (fa["title_translations"][locale].blank? ? File.basename(fa["url"]) : fa["title_translations"][locale] rescue '') }} rescue [] + links = fa["event_news_links"].map{|link| { "link_url" => link["url"], "link_title" => (link["title_translations"][locale].blank? ? link["url"] : link["title_translations"][locale]) } } rescue [] + + x = { + "event_news_links" => links, + "event_news_files" => files, + "title" => fa["title_translations"][locale], + "subtitle" => fa["subtitle_translations"][locale], + "statuses" => [status], + "category" => fa["category"], + "postdate" => fa["postdate"], + "author" => fa["author"], + "source-site" => "#{fa["source-site-title"]}", + "source-site-title" => fa["source-site-title"], + "source-site-link" => fa["source-site"], + "link_to_show" => OrbitHelper.url_to_show(fa["params"]), + "target" => "_self", + "img_src" => fa["image"]["thumb"] || "/assets/event_news-default.jpg", + "img_description" => fa["image_description_translations"][locale], + "more" => t(:more_plus), + "view_count" => "" + } + if (!x["title"].empty? rescue false) + fans << x + end + end + end + fans + end + def filter_by_keywords(sorted,keywords,stime,etime) + kflag = keywords.blank? + sflag = stime.blank? + eflag = etime.blank? + stime = stime.to_s.split('/') + stime = Time.zone.local(*stime) rescue nil + etime = etime.to_s.split('/') + etime = Time.zone.local(*etime) rescue nil + if !kflag || !sflag || !eflag + sorted.select{|anns| + if kflag + flag = true + else + if anns["source-site"].present? + title = Nokogiri::HTML(anns["title"].to_s).text + else + title = Nokogiri::HTML(anns.title.to_s).text + end + flag = title.include?(keywords.to_s) + end + if sflag && !eflag + flag = flag && (anns.event_date<=etime) + elsif !sflag && eflag + flag = flag && (anns.event_date>=stime) + elsif !sflag && !eflag + flag = flag && (anns.event_date>=stime) && (anns.event_date<=etime) + end + flag + } + else + sorted + end + end + def get_sorted_event_news(data_count=nil) + params = OrbitHelper.params + locale = OrbitHelper.get_site_locale.to_s + page_number = OrbitHelper.page_number.to_i + page_number = 1 if page_number == 0 + page_data_count = data_count || OrbitHelper.page_data_count.to_i + feeds_anns = [] + page = Page.where(url:params['url']).first + if @type == "show_widget" + tags = @tags + categories = @categories + else + tags = page.tags + categories = params['category']=='all' ? (page.categories || []) : ([Category.find(params['category'])] rescue (page.categories || [])) + end + if !params["source"].present? + if @type == "show_widget" + if params[:uids].blank? + event_news = EventNews.where(:title.nin => ["",nil],:is_preview.in=>[false,nil]) + .can_display_and_sorted.is_approved + .filter_by_categories(categories,false).filter_by_tags(tags).to_a + else + member_prfile = MemberProfile.any_in(:uid=>params[:uids]) + user_ids = member_prfile.map{|m| m.user.id rescue nil}.select{|id| !id.nil?} + event_news = EventNews.where(:title.nin => ["",nil],:is_preview.in=>[false,nil],:create_user_id.in=>user_ids) + .can_display_and_sorted.is_approved + .filter_by_categories(categories,false).filter_by_tags(tags).to_a + end + else + event_news = EventNews.where(:title.nin => ["",nil],:is_preview.in=>[false,nil]) + .can_display_and_sorted.is_approved + .filter_by_categories(categories,false).filter_by_tags(tags).to_a + end + if !(defined? SiteFeed).nil? + if @type != "show_widget" + feeds_anns = get_feed_event_news("index") + else + feeds_anns = [] + end + end + else + event_news = [] + if @type != "show_widget" + feeds_anns = get_feed_event_news("index",params["source"]) + else + feeds_anns = [] + end + end + if !feeds_anns.blank? + if event_news.count != 0 + top_anns = event_news.select{|v| v.is_top} + feeds_anns.select{|v| v['is_top']} + rest_all_anns = feeds_anns.select{|v| v['is_top'] != true} + event_news.select{|v| !v.is_top} + rest_anns = rest_all_anns.sort{|v1,v2| v2["event_date"]<=>v1["event_date"]} + all_sorted = top_anns.sort{|v1,v2| v2["event_date"]<=>v1["event_date"]} + rest_anns + else + all_sorted = feeds_anns.select{|v| v['is_top']}.sort{|v1,v2| v2["event_date"]<=>v1["event_date"]} + feeds_anns.select{|v| v['is_top'] != true}.sort{|v1,v2| v2["event_date"]<=>v1["event_date"]} + end + all_filter = filter_by_keywords(all_sorted,params[:keywords],params[:stime],params[:etime]) + else + all_filter = filter_by_keywords(event_news,params[:keywords],params[:stime],params[:etime]) + end + if page_data_count != 0 + sorted = all_filter[(page_number-1)*page_data_count...page_number*page_data_count] + else + sorted = all_filter + end + annc_count = all_filter.count + total_pages = page_data_count == 0 ? 1 : (annc_count.to_f / page_data_count).ceil + [sorted,total_pages] + end + def render_view_for_annc(overridehtml=nil) + @key = Site.first.template + def render_link_to_edit(html, url_to_edit) + if html.scan("{{link_to_edit}}").length == 0 + html = url_to_edit.blank? ? html : html + "

#{t(:edit)}

" + else + html = url_to_edit.blank? ? html.gsub("{{link_to_edit}}","") : html.gsub("{{link_to_edit}}","

#{t(:edit)}

") + end + return html + end + + def parsing_repeats_again(elements,d,level) + newhtml = [] + oldhtml = [] + elements.each do |el| + html_to_render = "" + data_name = el.attr("data-list") + wrap_elements = el.css("*[data-list][data-level='#{level}']") + if d[data_name] + d[data_name].each_with_index do |item,i| + element = el.inner_html + if wrap_elements.count > 0 + htmls = parsing_repeats_again(wrap_elements,d[data_name][i], level + 1) + htmls[0].each_with_index do |html,i| + element = element.gsub(html,htmls[1][i]) + end + end + item.each do |key,value| + if !value.kind_of?(Array) + value = value.nil? ? "" : value + element = element.gsub("{{#{key}}}",value.to_s.html_safe) + element = element.gsub("%7B%7B#{key}%7D%7D",value.to_s.html_safe) + element = render_link_to_edit(element, value) if key.eql?("url_to_edit") + end + end + html_to_render = html_to_render + element + end + temp = el.to_s + oldhtml << temp + temp = temp.gsub(el.inner_html, html_to_render) + newhtml << temp + end + end + [oldhtml,newhtml] + end + + + if @target_action == "index" + filename = overridehtml.nil? ? params[:layout_type] : overridehtml + f = File.join(Rails.root, 'app', 'templates', "#{@key}", 'modules', 'event_news', "#{filename}.html.erb") + if !File.exists?f + f = File.join(Rails.root, 'app', 'templates', "#{@key}", 'modules', 'event_news', "index.html.erb") + if !File.exists?f + return "
Maybe the administrator has changed the theme, please select the index page design again from the page settings.
".html_safe + end + end + file = File.open(f) + doc = Nokogiri::HTML(file, nil, "UTF-8") + file.close + controller = EventNewsModuleController.new + begin + data = @data# rescue nil + rescue Exception => e + write_debug_file(e,'event_news',@target_action) if Site::DEBUG + end + if !data.nil? + wrap_elements = doc.css("*[data-list][data-level='0']") + htmls = parsing_repeats_again(wrap_elements,data,1) + html = doc.to_s + htmls[0].each_with_index do |h,i| + html = html.gsub(h,htmls[1][i]) + end + extras = data["extras"] || {} + extras["page-title"] = Page.find_by(:page_id => params[:page_id]).name rescue "" if !extras["page-title"] + extras.each do |key,value| + value = value.nil? ? "" : value + html = html.gsub("{{#{key}}}",value.to_s.html_safe) + html = html.gsub("%7B%7B#{key}%7D%7D",value.to_s.html_safe) + end + total_pages = data['total_pages'].to_i rescue 1 + if total_pages > 1 + html = html.gsub("{{pagination_goes_here}}",create_pagination(total_pages)) + else + html = html.gsub("{{pagination_goes_here}}",""); + end + html.html_safe + else + return "
No content to show.
".html_safe + end + else + filename = overridehtml.nil? ? @target_action : overridehtml + f = File.join(Rails.root, 'app', 'templates', "#{@key}", 'modules', 'event_news', "#{filename}.html.erb") + if File.exists?f + file = File.open(f) + doc = Nokogiri::HTML(file, nil, "UTF-8") + file.close + controller = EventNewsModuleController.new + begin + data = @data# rescue nil + rescue Exception => e + write_debug_file(e,'event_news',@target_action) if Site::DEBUG + end + if data.nil? + return "
No content to show.
".html_safe + end + + if data.blank? || data.empty? + file = File.open("#{Rails.root}/app/views/errors/404.html") + doc = Nokogiri::HTML(file, nil, "UTF-8") + file.close + doc.to_html.html_safe + else + unless data['impressionist'].blank? + Thread.new do + impression = data['impressionist'].impressions.create + impression.user_id = request.session['user_id'] + impression.controller_name = 'event_news' + impression.action_name = @target_action + impression.ip_address = request.remote_ip + impression.session_hash = request.session.id + impression.request_hash = @impressionist_hash + impression.referrer = request.referrer + impression.save + end + data['impressionist'].inc(view_count: 1) + data["data"]["view_count"] = data["impressionist"].view_count if data["data"].present? + end + wrap_elements = doc.css("*[data-list][data-level='0']") + if wrap_elements.count == 0 + wrap_element_html = doc.to_s + el = wrap_element_html + data.each do |key,value| + next if key.eql? 'impressionist' + value = value.nil? ? "" : value + el = el.gsub("{{#{key}}}",value.to_s.html_safe) + el = el.gsub("%7B%7B#{key}%7D%7D",value.to_s.html_safe) + end + el.html_safe + else + keys = data.keys + not_array_key = nil + data.keys.each do |key| + not_array_key = key if data["#{key}"].kind_of?(Hash) + end + htmls = parsing_repeats_again(wrap_elements,data,1) + html = doc.to_s + htmls[0].each_with_index do |h,i| + html = html.gsub(h,htmls[1][i]) + end + extras = data["#{not_array_key}"] || {} + extras.each do |key,value| + next if key.eql? 'impressionist' + value = value.nil? ? "" : value + html = html.gsub("{{#{key}}}",value.to_s) + html = html.gsub("%7B%7B#{key}%7D%7D",value.to_s) + end + html = render_link_to_edit(html, data["url_to_edit"]) if !data["url_to_edit"].nil? + total_pages = data['total_pages'].to_i rescue 1 + if @show_page == "false" + html = html.gsub("{{pagination_goes_here}}","") + else + if total_pages > 1 + html = html.gsub("{{pagination_goes_here}}",create_pagination(total_pages)) + else + html = html.gsub("{{pagination_goes_here}}","") + end + end + html = Nokogiri::HTML.parse(html) + html.css('.i-annc__page-title').remove + dates = html.css("*[date-format]") + if !dates.blank? + dates.each do |d| + format = d.attributes["date-format"].value + date = DateTime.parse(d.inner_text) + d.inner_html = d.inner_html.gsub(d.inner_text.strip, " " + date.strftime(format)) + end + end + html.css("body").to_html.html_safe + end + end + else + return "
There is a problem with the design. We will try to fix it as soon as possible. Sorry for the inconvenience!! :(
".html_safe + end + end + end + def get_layouts(module_app) + layout_types = [] + @key = Site.first.template + f = File.join("#{Rails.root}/app/templates/#{@key}/modules/#{module_app}/info.json") + if File.exists?f + info = File.read(f) + hash = JSON.parse(info) rescue {} + frontends = hash["frontend"] || [] + frontends.each do |frontend| + frontend["thumbnail"] = "/assets/#{module_app}/thumbs/#{frontend["thumbnail"]}" + layout_types << frontend + end + end + if layout_types.empty? + Dir.glob("#{Rails.root}/app/templates/#{@key}/modules/#{module_app}/*").each do |w| + next if File.ftype(w).eql?("directory") + w = File.basename(w, ".*") + w = File.basename(w, ".*") + if w[0,1] != "_" && w[0,1] != "s" && w != "info" + layout_types << w + end + end + end + layout_types + end +end diff --git a/app/mailers/.keep b/app/mailers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/.keep b/app/models/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/models/event_news.rb b/app/models/event_news.rb new file mode 100644 index 0000000..ae52b82 --- /dev/null +++ b/app/models/event_news.rb @@ -0,0 +1,173 @@ +class EventNews + include Mongoid::Document + include Mongoid::Timestamps + + include OrbitModel::Status + include OrbitModel::Impression + # encoding: utf-8 + include OrbitTag::Taggable + include OrbitCategory::Categorizable + include Slug + require 'event_news_model/cache' + include EventNewsModel::Cache + SubPart.class_eval { include EventNewsModel::Cache } + Page.class_eval { include EventNewsModel::Cache } + before_destroy do + EventNewsCache.all.destroy + end + field :add_to_calendar,type: Boolean,default: false + field :calendar_start_date, :type => DateTime + field :calendar_end_date, :type => DateTime + field :calendar_all_day,type: Boolean,default: false + field :calendar_type_id + field :event_id + + field :title, type: String, localize: true + field :speaker, type: String, localize: true + field :host, type: String, localize: true + field :subtitle, localize: true + field :text, localize: true + field :notes, localize: true + field :create_user_id + field :update_user_id + field :public, :type => Boolean, :default => true + field :event_date , :type => DateTime, :default => Time.now + field :postdate , :type => DateTime, :default => Time.now + field :deadline , :type => DateTime + field :rss2_sn + field :approved, :type => Boolean, :default => false + field :is_preview, :type => Boolean, :default => false + field :expirable_created_at, type: DateTime + field :rejected, :type => Boolean, :default => false + field :reapproval, :type => Boolean, :default => false + field :rejection_reason + field :is_external_link, :type => Boolean, :default => false + field :external_link + field :display_subtitle, :type => Boolean, :default => false + field :display_img, :type => Boolean, :default => false + + field :email_id + field :email_sent, :type => Boolean, :default => false + field :email_sentdate , :type => DateTime + field :email_member_ids + field :other_mailaddress + field :image_description, localize: true + field :top_end_date, :type => DateTime + + mount_uploader :image, ImageUploader + + has_many :event_news_links, :autosave => true, :dependent => :destroy + has_many :event_news_files, :autosave => true, :dependent => :destroy + + accepts_nested_attributes_for :event_news_files, :allow_destroy => true + accepts_nested_attributes_for :event_news_links, :allow_destroy => true + + before_destroy :destroy_email + + scope :can_display_and_sorted, ->{where(:is_hidden=>false,:is_preview => false).any_of({:postdate.lte=>Time.now, :deadline.gte=>Time.now},{:postdate.lte=>Time.now, :deadline=>nil}).order(is_top: :desc,postdate: :desc,id: :desc)} + scope :is_approved, ->{where(:approved => true)} + + before_create :set_expire + before_save :check_limit + + def calendar_type + CalendarType.where(:category_id.in => self.calendar_type_id) + end + def event + if !self.event_id.nil? + Event.where(:id => self.event_id).first + else + nil + end + end + def check_limit + check_status_limit(update_user) + end + def check_status_limit(user,check_only=false) + role_ids = user.member_profile.roles.map(&:id) rescue [] + status_settings = (role_ids.collect do |role_id| + EventNewsSetting.first.event_news_status_settings.select{|v| v.role_id.to_s == role_id.to_s} + end.flatten rescue []) + reach_limit = [] + if status_settings.count != 0 + reach_limit = status_settings.collect do |status_setting| + status = status_setting.status + if status_setting.top_limit.to_i <= self.class.where(:update_user_id.in => Role.find(status_setting.role_id).member_profiles.collect(&:user).flatten.uniq.map{|v| v.id},status => true).count + if !check_only + if self[status] && !self.class.where(id:self.id).first[status] + self[status] = false + nil + end + else + status + end + else + nil + end + end.compact + reach_limit = reach_limit.group_by{|v| v}.collect do |k,v| + if v.count >= user.member_profile.roles.count + k + else + nil + end + end.compact + end + reach_limit + end + def slug_title + doc = Nokogiri::HTML(self.title) + title = doc.text.gsub('/','-') + end + def set_expire + self.expirable_created_at = Time.now if self.is_preview + return true + end + + def update_user + User.find(update_user_id) rescue nil + end + + def update_user=(user) + self.update_user_id = user.id + end + + def email_members + MemberProfile.find(self.email_member_ids) rescue [] + end + + def email_addresses + addresses = self.email_members.collect{|member| member.email} rescue [] + addresses = addresses +[self.other_mailaddress] if !self.other_mailaddress.blank? + addresses.flatten + end + + def email + mail = Email.find(self.email_id) rescue nil + end + + def expired? + (self.deadline < Time.now) rescue false + end + + def destroy_email + mail = Email.find(self.email_id) rescue nil + mail.destroy if !mail.nil? + end + + def self.remove_expired_status + self.where(:is_top => true, :top_end_date.ne => nil, :top_end_date.lt => Time.now).each do |b| + b.is_top = false + b.top_end_date = nil + b.save + end + end + + def display_subtitle? + self.display_subtitle rescue false + end + + def display_img? + self.display_img rescue false + end +end diff --git a/app/models/event_news_cache.rb b/app/models/event_news_cache.rb new file mode 100644 index 0000000..b6ddf57 --- /dev/null +++ b/app/models/event_news_cache.rb @@ -0,0 +1,6 @@ +class EventNewsCache + include Mongoid::Document + field :parent_id + field :filter_result + field :locale,type: String,default: 'zh_tw' +end \ No newline at end of file diff --git a/app/models/event_news_feed.rb b/app/models/event_news_feed.rb new file mode 100644 index 0000000..8abe2eb --- /dev/null +++ b/app/models/event_news_feed.rb @@ -0,0 +1,9 @@ +class EventNewsFeed + include Mongoid::Document + include Mongoid::Timestamps + include Slug + + field :title, as: :slug_title, type: String, localize: true + field :tag_ids, type: Array, default: [] + +end \ No newline at end of file diff --git a/app/models/event_news_file.rb b/app/models/event_news_file.rb new file mode 100644 index 0000000..20edc7e --- /dev/null +++ b/app/models/event_news_file.rb @@ -0,0 +1,24 @@ +# encoding: utf-8 +class EventNewsFile + + include Mongoid::Document + include Mongoid::Timestamps + + mount_uploader :file, AssetUploader + + field :description, localize: true + field :title, localize: true + field :choose_lang, :type => Array, :default => ["en","zh_tw"] + + belongs_to :event_news + + + def enabled_for?(lang) + if lang.nil? + return true + else + return self.choose_lang.include?(lang) + end + end + +end diff --git a/app/models/event_news_link.rb b/app/models/event_news_link.rb new file mode 100644 index 0000000..5e56a58 --- /dev/null +++ b/app/models/event_news_link.rb @@ -0,0 +1,25 @@ +# encoding: utf-8 +require 'uri' + +class EventNewsLink + include Mongoid::Document + include Mongoid::Timestamps + + field :url + field :title, localize: true + + belongs_to :event_news + + before_validation :add_http + + validates :url, :presence => true, :format => /\A(http|https):\/\/(([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5})|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:[0-9]{1,5})?(\/.*)?\Z/i + + protected + + def add_http + unless self.url[/^http:\/\//] || self.url[/^https:\/\//] + self.url = 'http://' + self.url + end + end + +end \ No newline at end of file diff --git a/app/models/event_news_setting.rb b/app/models/event_news_setting.rb new file mode 100644 index 0000000..2f46415 --- /dev/null +++ b/app/models/event_news_setting.rb @@ -0,0 +1,23 @@ +class EventNewsSetting + include Mongoid::Document + include Mongoid::Timestamps + + field :top_limit, type: Integer, :default => 0 + field :pro_enabled, type: Boolean, :default => false + field :approvers, type: Array, :default => [] + field :email_to, type: Array, :default => ["admins","managers","approvers"] + field :is_display_edit_only, type: Boolean, :default => false + field :only_manager_can_edit_status, type: Boolean, :default => false + has_many :event_news_status_settings, :autosave => true, :dependent => :destroy + accepts_nested_attributes_for :event_news_status_settings, :allow_destroy => true + def self.check_limit_for_user(user_id, b_id = nil) + limit = self.first.top_limit rescue 0 + return true if limit == 0 + count = Bulletin.where(:is_top => true, :create_user_id => user_id, :id.ne => b_id).count + return count < limit + end + + def self.is_pro? + self.first.pro_enabled rescue false + end +end \ No newline at end of file diff --git a/app/models/event_news_status_setting.rb b/app/models/event_news_status_setting.rb new file mode 100644 index 0000000..6cce87f --- /dev/null +++ b/app/models/event_news_status_setting.rb @@ -0,0 +1,7 @@ +class EventNewsStatusSetting + include Mongoid::Document + field :role_id + field :status + field :top_limit + belongs_to :event_news_setting +end \ No newline at end of file diff --git a/app/views/.keep b/app/views/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/views/admin/event_news/_approval_modal.html.erb b/app/views/admin/event_news/_approval_modal.html.erb new file mode 100644 index 0000000..5bf22e1 --- /dev/null +++ b/app/views/admin/event_news/_approval_modal.html.erb @@ -0,0 +1,122 @@ + + \ No newline at end of file diff --git a/app/views/admin/event_news/_edit_feed_form.html.erb b/app/views/admin/event_news/_edit_feed_form.html.erb new file mode 100644 index 0000000..99af240 --- /dev/null +++ b/app/views/admin/event_news/_edit_feed_form.html.erb @@ -0,0 +1,38 @@ +<%= form_for @event_news_feed, url: admin_event_news_updatefeed_path(:id => @event_news_feed.id), html: {class: "form-horizontal main-forms"} do |f| %> +
+ <% @site_in_use_locales.each do |locale| %> + <%= f.fields_for :title_translations do |f| %> +
+ +
+ <%= f.text_field locale, data: {"fv-validation" => "required;","fv-messages" => "Cannot be empty.;"}, value: (@event_news_feed.title_translations[locale.to_s] rescue nil) %> +
+
+ <% end %> + <% end %> +
+
+
+ +
+
+
+<% end %> + + \ No newline at end of file diff --git a/app/views/admin/event_news/_feed.html.erb b/app/views/admin/event_news/_feed.html.erb new file mode 100644 index 0000000..1656396 --- /dev/null +++ b/app/views/admin/event_news/_feed.html.erb @@ -0,0 +1,51 @@ + + + <%= feed.title %> +
+ +
+ + +
+
+ +
+
+ + + RSS Feed + + + JSON Feed + + \ No newline at end of file diff --git a/app/views/admin/event_news/_feed_form.html.erb b/app/views/admin/event_news/_feed_form.html.erb new file mode 100644 index 0000000..16bd93a --- /dev/null +++ b/app/views/admin/event_news/_feed_form.html.erb @@ -0,0 +1,38 @@ +<%= form_for @event_news_feed, url: admin_event_news_createfeed_path, html: {class: "form-horizontal main-forms"} do |f| %> +
+ <% @site_in_use_locales.each do |locale| %> + <%= f.fields_for :title_translations do |f| %> +
+ +
+ <%= f.text_field locale, data: {"fv-validation" => "required;","fv-messages" => "Cannot be empty.;"}, value: (@event_news_feed.title_translations[locale.to_s] rescue nil) %> +
+
+ <% end %> + <% end %> +
+ +
+<% end %> + + \ No newline at end of file diff --git a/app/views/admin/event_news/_form.html.erb b/app/views/admin/event_news/_form.html.erb new file mode 100644 index 0000000..d35e90b --- /dev/null +++ b/app/views/admin/event_news/_form.html.erb @@ -0,0 +1,603 @@ +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag "lib/main-forms" %> + <%= stylesheet_link_tag "lib/fileupload" %> + <%= stylesheet_link_tag "lib/main-list" %> +<% end %> + +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "lib/bootstrap-fileupload" %> + <%= javascript_include_tag "lib/bootstrap-datetimepicker" %> + <%= javascript_include_tag "lib/datetimepicker/datetimepicker.js" %> + <%= javascript_include_tag "lib/file-type" %> + <%= javascript_include_tag "lib/module-area" %> + <%= javascript_include_tag "form" %> +<% end %> + + +
+ + + + + +
+ + +
+ + +
+ +
+ <%= select_category(f, @module_app) %> +
+
+ + +
+ +
+ <%= f.datetime_picker :event_date, :no_label => true, :new_record => @event_news.new_record?, :data=>{"picker-type" => "range", "range" => "start"} %> +
+
+
+ +
+ <%= f.datetime_picker :postdate, :no_label => true, :new_record => @event_news.new_record?, :data=>{"picker-type" => "range", "range" => "start"} %> +
+
+ +
+ +
+ <%= f.datetime_picker :deadline, :no_label => true, :new_record => @event_news.new_record?, :data=>{"picker-type" => "range", "range" => "end"} %> +
+
+ +
+ <%= f.label :is_external_link, t("event_news.is_external_link"), :class => "control-label muted" %> +
+ <%= f.check_box :is_external_link %> +
+
+ + + + +
+ <%= f.label :display_subtitle, t("event_news.display_subtitle"), :class => "control-label muted" %> +
+ <%= f.check_box :display_subtitle %> +
+
+ + +
+ <%= f.label :display_img, t("event_news.display_img"), :class => "control-label muted" %> +
+ <%= f.check_box :display_img %> +
+
+
+ + + <% if defined? Calendar %> +
+
+ +
+ <%= f.check_box :add_to_calendar,onchange: 'trigger_on_add_calendar(this)' %> +
+
+
> +
+ +
+ <%= f.select :calendar_type_id, @calendar_categories.collect{|t| [ t.title, t.id ]} %> +
+
+
+
+ + +
+
+ <%= f.datetime_picker :calendar_start_date, :new_record => @event_news.new_record?, :no_label => true, :data=>{"picker-type" => "range", "range" => "start"} %> +
+
+
+
+ + +
+
+ <%= f.datetime_picker :calendar_end_date, :new_record => @event_news.new_record?, :no_label => true, :data=>{"picker-type" => "range", "range" => "end"} %> +
+
+
+ +
+ <%= f.check_box :calendar_all_day %> +
+
+
+ <%= f.hidden_field :event_id %> +
+ <% end %> + + <% if((!AnnouncementSetting.first.only_manager_can_edit_status) || (AnnouncementSetting.first.only_manager_can_edit_status && (@current_user.is_admin? || @current_user.is_manager?(@module_app))) ) %> +
+ +
+ +
+ <% if !(@reach_limit.include?('is_top') && @event_news.is_top != true) || current_user.is_admin? %> + + <% else %> + + <% end %> + <% if !(@reach_limit.include?('is_hot') && @event_news.is_hot != true) || current_user.is_admin? %> + + <% else %> + + <% end %> + +
+
+ <% if !@event_news.is_top? && !AnnouncementSetting.check_limit_for_user((@event_news.new_record? ? current_user.id : @event_news.create_user_id)) %> + Top limit has been reached. The event_news wont be marked as top even if you click on it. + <% end %> +
+
+
" data-for="is_top"> + +
+ <%= f.datetime_picker :top_end_date, :no_label => true, :new_record => @event_news.new_record? %> +
+
+ +
+ <% end %> + + +
+
+ + <%= select_tags(f, @module_app) %> +
+
+ + +
+ + +
+ +
+
+
+ <% if @event_news.image.file %> + <%= image_tag @event_news.image %> + <% else %> + + <% end %> +
+
+ + <%= t(:select_image) %> + <%= t(:change) %> + <%= f.file_field :image %> + + <%= t(:cancel) %> +
+ +
+
+
+
+ <% @site_in_use_locales.each do |locale| %> + <%= f.fields_for :image_description_translations do |f| %> +
+ +
+ <%= f.text_field locale, value: (@event_news.image_description_translations[locale.to_s] rescue nil) %> +
+
+ <% end %> + <% end %> + +
+ + + +
+ + +
+ +
+ + + +
+ <%= render partial: 'admin/member_selects/email_selection_box', locals: {field: 'event_news[email_member_ids][]', email_members: @event_news.email_members} %> +
+
+
+
+ +
+
+ <%= "#{t("event_news.other_mailaddress")}(#{t("event_news.other_mailaddress_note")})"%> + <%= f.text_area :other_mailaddress, :class=>"span12", :cols=>"25", :rows=>"10" %> +
+
+
+ +
+
+ +
+ <%= f.datetime_picker :email_sentdate, :no_label => true %> +
+
+
+ + <% if (@event_news.email.is_sent rescue false) %> +
+
+ +
+ +
+
+
+ <% end %> + +
+ +
+ + + + + + +
+ + <% @site_in_use_locales.each_with_index do |locale, i| %> + +
"> + + +
+ +
+ <%= f.fields_for :title_translations do |f| %> + <%= f.text_area locale, class: "ckeditor_reduce input-block-level", placeholder: t(:title), value: (@event_news.title_translations[locale] rescue nil) %> + <% end %> +
+
+ +
+ +
+ <%= f.fields_for :speaker_translations do |f| %> + <%= f.text_field locale, class: "input-block-level", placeholder: t("event_news.speaker"), value: (@event_news.speaker_translations[locale] rescue nil) %> + <% end %> +
+
+ +
+ +
+ <%= f.fields_for :host_translations do |f| %> + <%= f.text_field locale, class: "input-block-level", placeholder: t("event_news.host"), value: (@event_news.host_translations[locale] rescue nil) %> + <% end %> +
+
+ +
+ +
+
+ <%= f.fields_for :subtitle_translations do |f| %> + <%= f.text_area locale, rows: 2, class: "ckeditor input-block-level", value: (@event_news.subtitle_translations[locale] rescue nil) %> + <% end %> +
+
+
+ + +
+ +
+
+ <%= f.fields_for :text_translations do |f| %> + <%= f.cktext_area locale, rows: 5, class: "input-block-level", :value => (@event_news.text_translations[locale] rescue nil) %> + <% end %> +
+
+
+ +
+ +
+
+ <%= f.fields_for :notes_translations do |f| %> + <%= f.cktext_area locale, rows: 5, class: "input-block-level", :value => (@event_news.notes_translations[locale] rescue nil) %> + <% end %> +
+
+
+ +
+ + <% end %> + + +
+ +
+ + + <% if @event_news && !@event_news.event_news_links.blank? %> +
+ <% @event_news.event_news_links.each_with_index do |event_news_link, i| %> + <%= f.fields_for :event_news_links, event_news_link do |f| %> + <%= render :partial => 'form_link', :object => event_news_link, :locals => {:f => f, :i => i} %> + <% end %> + <% end %> +
+
+ <% end %> + + +
+
+

+ <%= hidden_field_tag 'event_news_link_field_count', @event_news.event_news_links.count %> + <%= t(:add) %> +

+ +
+
+ + +
+ +
+ + + <% if @event_news && !@event_news.event_news_files.blank? %> +
+ <% @event_news.event_news_files.each_with_index do |event_news_file, i| %> + <%= f.fields_for :event_news_files, event_news_file do |f| %> + <%= render :partial => 'form_file', :object => event_news_file, :locals => {:f => f, :i => i} %> + <% end %> + <% end %> +
+
+ <% end %> + + +
+
+

+ <%= hidden_field_tag 'event_news_file_field_count', @event_news.event_news_files.count %> + <%= t(:add) %> +

+ +
+
+ +
+ +
+ + +
+ <%= get_referer_url[:action] rescue "" %> + <%= f.submit t('submit'), class: 'btn btn-primary' %> + + <%= button_tag t("preview"), id: "button_for_preview", name: "commit", class: 'btn', type: :button %> + <%= link_to t('cancel'), admin_event_news_index_path, :class=>"btn" %> +
+ + + + +<% if !@module_app.tags.empty? %> + +<% end %> +<% content_for :page_specific_javascript do %> + +<% end %> diff --git a/app/views/admin/event_news/_form_file.html.erb b/app/views/admin/event_news/_form_file.html.erb new file mode 100644 index 0000000..8d37ff1 --- /dev/null +++ b/app/views/admin/event_news/_form_file.html.erb @@ -0,0 +1,69 @@ +<% if form_file.new_record? %> +
+<% else %> +
+ <% if form_file.file.blank? %> + <%= t(:no_file) %> + <% else %> + <%= link_to content_tag(:i) + form_file.file_identifier, form_file.file.url, {:class => 'file-link file-type', :target => '_blank', :title => form_file.file_identifier} %> + <% end %> +<% end %> +
+ + + + <% @site_in_use_locales.each_with_index do |locale, i| %> + <%= locale %>"> + <%= f.fields_for :title_translations do |f| %> + <%= f.text_field locale, :class => "input-medium", placeholder: t(:alternative), :value => (form_file.title_translations[locale] rescue nil) %> + <% end %> + + <% end %> + + + + <% @site_in_use_locales.each_with_index do |locale, i| %> + <%= locale %>"> + <%= f.fields_for :description_translations do |f| %> + <%= f.text_field locale, :class => "input-medium", placeholder: t(:description), :value => (form_file.description_translations[locale] rescue nil) %> + <% end %> + + <% end %> + + + + + + <%= hidden_field_tag 'event_news[event_news_files_attributes][0][choose_lang][]', '' %> + + <% if form_file.new_record? %> + + + + <% else %> + + <%= f.hidden_field :id %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + + <% end %> +
+
\ No newline at end of file diff --git a/app/views/admin/event_news/_form_link.html.erb b/app/views/admin/event_news/_form_link.html.erb new file mode 100644 index 0000000..461a3fc --- /dev/null +++ b/app/views/admin/event_news/_form_link.html.erb @@ -0,0 +1,26 @@ +
+ + <%= f.text_field :url, class: "input-large", placeholder: t(:url) %> + + + <% @site_in_use_locales.each_with_index do |locale, i| %> + <%= locale %>"> + <%= f.fields_for :title_translations do |f| %> + <%= f.text_field locale, :class => "input-large", placeholder: t(:url_alt), :value => (form_link.title_translations[locale] rescue nil) %> + <% end %> + + <% end %> + + + <% if form_link.new_record? %> + + + + <% else %> + + <%= f.hidden_field :id %> + + <%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %> + + <% end %> +
diff --git a/app/views/admin/event_news/_index.html.erb b/app/views/admin/event_news/_index.html.erb new file mode 100644 index 0000000..e06c9ea --- /dev/null +++ b/app/views/admin/event_news/_index.html.erb @@ -0,0 +1,98 @@ + + + + + + <% @table_fields.each do |f| %> + <%= thead(f) %> + <% end %> + + + + <% @event_news.each do |b| %> + + + + + + + + + + + + + <% end %> + +
+ <%= b.status_for_table %> + + <%= b.category.title rescue "" %> + <% if (b.category.disable rescue false) %> + <%= t(:disabled) %> + <% end %> + + <% if b.expired? || (b.category.disable rescue false)%> + <%= b.title.to_s.html_safe %> + <% else %> + <%= b.title.to_s.html_safe %> + <% end %> + + <% if b.expired? %> + <%= t(:expired) %> + <% end %> + + <% if b.reapproval %> + <%= t("event_news.reapproval") + " " + t(:pending) %> + <% end %> + <% if b.rejected %> + <%= t(:rejected) %> : <%= b.rejection_reason rescue "" %> + <% end %> + <% if !b.approved? && !b.rejected %> + <%= t(:pending) %> + <% end %> +
+ +
+
<%= format_value b.event_date %><%= format_value b.postdate %>"><%= format_value b.deadline %><%= b.update_user.user_name rescue ""%>
+
" class="footable-row-detail-inner" style="display: none;"> +
+ <%= t(:view_count) %> : + <%= b.view_count %> +
+
+ <%= t(:tags) %> : + <% b.tags.each do |tag| %> + <%= tag.name %> + <% end %> +
+
+ <%= t("event_news.email_to") %> : + <% b.email_members.each do |member| %> + <%= member.name %> + <% end %> + <% unless b.other_mailaddress.nil? %> + <% b.other_mailaddress.split(',').each do |mailaddress| %> + <%= mailaddress %> + <% end %> + <% end %> +
+
+
+ +<%= + content_tag :div, class: "bottomnav clearfix" do + content_tag :div, paginate(@event_news), class: "pagination pagination-centered" + end +%> \ No newline at end of file diff --git a/app/views/admin/event_news/edit.html.erb b/app/views/admin/event_news/edit.html.erb new file mode 100644 index 0000000..d9439fa --- /dev/null +++ b/app/views/admin/event_news/edit.html.erb @@ -0,0 +1,5 @@ +<%= form_for @event_news, url: admin_event_news_path(@event_news), html: {class: "form-horizontal main-forms previewable"} do |f| %> +
+ <%= render :partial => 'form', locals: {f: f} %> +
+<% end %> \ No newline at end of file diff --git a/app/views/admin/event_news/excel_format.xlsx.axlsx b/app/views/admin/event_news/excel_format.xlsx.axlsx new file mode 100644 index 0000000..3d54725 --- /dev/null +++ b/app/views/admin/event_news/excel_format.xlsx.axlsx @@ -0,0 +1,150 @@ +# encoding: utf-8 + +wb = xlsx_package.workbook + +wb.add_worksheet(name: "EventNewsModule") do |sheet| + + heading = sheet.styles.add_style(:b => true, :locked => true) + example = sheet.styles.add_style(:i => true) + row = [] + row1 = [] + row2 = [] + + row << t("category") + row1 << "select" + t = "" + @module_app.categories.asc(:created_at).each_with_index do |cat,i| + t = t + "#{i}" + " -> " + cat.title + ", " + end + if @module_app.categories.count > 0 + t = t + " Example : 0" + else + t = "Leave this field blank" + end + row2 << t + + row << t("tags") + row1 << "select" + t = "" + @module_app.tags.asc(:created_at).each_with_index do |tag,i| + t = t + "#{i}" + " -> " + tag.name + ", " + end + if @module_app.tags.count > 0 + t = t + " Example : 0,1,2" + else + t = "Leave this field blank" + end + row2 << t + + row << t("event_news.event_date") + row1 << "date" + row2 << "Format: YYYY/MM/DD, Example: 2015/12/10" + + row << t("event_news.start_date") + row1 << "date" + row2 << "Format: YYYY/MM/DD, Example: 2015/12/10" + + row << t("event_news.end_date") + row1 << "date" + row2 << "Format: YYYY/MM/DD, Example: 2015/12/12" + + row << t("top") + row1 << "boolean" + row2 << "0 for false, 1 for true" + + row << t("hot") + row1 << "boolean" + row2 << "0 for false, 1 for true" + + row << t("hide") + row1 << "boolean" + row2 << "0 for false, 1 for true " + + row << t("image") + row1 << "url" + row2 << "http://www.example.com/images/example.png" + + row << t("image") + " " + t("description") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("image") + " " + t("description") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("title") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("title") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("event_news.speaker") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("event_news.speaker") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("event_news.host") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("event_news.host") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("subtitle") + " - " + t("en") + row1 << "textarea" + row2 << "" + row << t("subtitle") + " - " + t("zh_tw") + row1 << "textarea" + row2 << "" + + row << t("content") + " - " + t("en") + row1 << "editor" + row2 << "" + row << t("content") + " - " + t("zh_tw") + row1 << "editor" + row2 << "" + + row << t("event_news.notes") + " - " + t("en") + row1 << "editor" + row2 << "" + row << t("event_news.notes") + " - " + t("zh_tw") + row1 << "editor" + row2 << "" + + row << t("link") + row1 << "textfield" + row2 << "Seperate with ';'. Example: http://rulingcom.com; http://google.com" + + row << t("link") + " " + t("url_alt") + " - " + t("en") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Rulingcom official site; Google search engine" + row << t("link") + " " + t("url_alt") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Rulingcom official site; Google search engine" + + row << t("file_") + row1 << "textfield" + row2 << "Seperate with ';'. Example: http://www.example.com/images/example.png; http://www.example.com/images/example2.png" + + row << t("file_") + " " + t("description") + " - " + t("en") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Great view; Nice potrait" + row << t("file_") + " " + t("description") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Great view; Nice potrait" + + row << t("file_") + " " + t("alternative") + " - " + t("en") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : example1; example2" + row << t("file_") + " " + t("alternative") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : example1; example2" + + + sheet.add_row row, :style => heading + sheet.add_row row1 + sheet.add_row row2, :style => example + +end \ No newline at end of file diff --git a/app/views/admin/event_news/export_excel.xlsx.axlsx b/app/views/admin/event_news/export_excel.xlsx.axlsx new file mode 100644 index 0000000..04b3b8b --- /dev/null +++ b/app/views/admin/event_news/export_excel.xlsx.axlsx @@ -0,0 +1,209 @@ +# encoding: utf-8 + +wb = xlsx_package.workbook + +wb.add_worksheet(name: "EventNewsModule") do |sheet| + + heading = sheet.styles.add_style(:b => true, :locked => true) + example = sheet.styles.add_style(:i => true) + row = [] + row1 = [] + row2 = [] + + row << t("category") + row1 << "select" + t = "" + categories = @module_app.categories.asc(:created_at) + categories.each_with_index do |cat,i| + t = t + "#{i}" + " -> " + cat.title + ", " + end + if categories.count > 0 + t = t + " Example : 0" + else + t = "Leave this field blank" + end + row2 << t + + row << t("tags") + row1 << "select" + t = "" + tags = @module_app.tags.asc(:created_at) + tags.each_with_index do |tag,i| + t = t + "#{i}" + " -> " + tag.name + ", " + end + if tags.count > 0 + t = t + " Example : 0,1,2" + else + t = "Leave this field blank" + end + row2 << t + + row << t("event_news.event_date") + row1 << "date" + row2 << "Format: YYYY/MM/DD, Example: 2015/12/10" + + row << t("event_news.start_date") + row1 << "date" + row2 << "Format: YYYY/MM/DD, Example: 2015/12/10" + + row << t("event_news.end_date") + row1 << "date" + row2 << "Format: YYYY/MM/DD, Example: 2015/12/12" + + row << t("top") + row1 << "boolean" + row2 << "0 for false, 1 for true" + + row << t("hot") + row1 << "boolean" + row2 << "0 for false, 1 for true" + + row << t("hide") + row1 << "boolean" + row2 << "0 for false, 1 for true " + + row << t("image") + row1 << "url" + row2 << "http://www.example.com/images/example.png" + + row << t("image") + " " + t("description") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("image") + " " + t("description") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("title") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("title") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("event_news.speaker") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("event_news.speaker") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("event_news.host") + " - " + t("en") + row1 << "textfield" + row2 << "" + row << t("event_news.host") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "" + + row << t("subtitle") + " - " + t("en") + row1 << "textarea" + row2 << "" + row << t("subtitle") + " - " + t("zh_tw") + row1 << "textarea" + row2 << "" + + row << t("content") + " - " + t("en") + row1 << "editor" + row2 << "" + row << t("content") + " - " + t("zh_tw") + row1 << "editor" + row2 << "" + + row << t("event_news.notes") + " - " + t("en") + row1 << "editor" + row2 << "" + row << t("event_news.notes") + " - " + t("zh_tw") + row1 << "editor" + row2 << "" + + row << t("link") + row1 << "textfield" + row2 << "Seperate with ';'. Example: http://rulingcom.com; http://google.com" + + row << t("link") + " " + t("url_alt") + " - " + t("en") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Rulingcom official site; Google search engine" + row << t("link") + " " + t("url_alt") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Rulingcom official site; Google search engine" + + row << t("file_") + row1 << "textfield" + row2 << "Seperate with ';'. Example: http://www.example.com/images/example.png; http://www.example.com/images/example2.png" + + row << t("file_") + " " + t("description") + " - " + t("en") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Great view; Nice potrait" + row << t("file_") + " " + t("description") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : Great view; Nice potrait" + + row << t("file_") + " " + t("alternative") + " - " + t("en") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : example1; example2" + row << t("file_") + " " + t("alternative") + " - " + t("zh_tw") + row1 << "textfield" + row2 << "Seperate with ';' with respective to the links in the link columns. Example : example1; example2" + + + sheet.add_row row, :style => heading + sheet.add_row row1 + sheet.add_row row2, :style => example + + @event_news.each do |anns| + row = [] + row << categories.to_a.index(anns.category) + t = [] + anns.tags.each do |tag| + t << tags.to_a.index(tag) + end + row << t.join(",") + row << (anns.event_date.strftime("%Y/%m/%d") rescue "") + row << (anns.postdate.strftime("%Y/%m/%d") rescue "") + row << (anns.deadline.strftime("%Y/%m/%d") rescue "") + row << (anns.is_top? ? 1 : 0) + row << (anns.is_hot? ? 1 : 0) + row << (anns.is_hidden? ? 1 : 0) + row << ("http://" + request.host_with_port + anns.image.url rescue "") + row << anns.image_description_translations["en"] + row << anns.image_description_translations["zh_tw"] + row << anns.title_translations["en"] + row << anns.title_translations["zh_tw"] + row << anns.speaker_translations["en"] + row << anns.speaker_translations["zh_tw"] + row << anns.host_translations["en"] + row << anns.host_translations["zh_tw"] + row << anns.subtitle_translations["en"] + row << anns.subtitle_translations["zh_tw"] + row << anns.text_translations["en"] + row << anns.text_translations["zh_tw"] + row << anns.notes_translations["en"] + row << anns.notes_translations["zh_tw"] + + links = anns.event_news_links.asc(:created_at) + t = links.collect{|l|l.url} + row << t.join(";") + t = links.collect{|l|l.title_translations["en"]} + row << t.join(";") + t = links.collect{|l|l.title_translations["zh_tw"]} + row << t.join(";") + + files = anns.event_news_files.asc(:created_at) + t = files.collect{|f|("http://" + request.host_with_port + f.file.url rescue nil)} + t.delete(nil) + row << t.join(";") + t = files.collect{|l|l.description_translations["en"]} + row << t.join(";") + t = files.collect{|l|l.description_translations["zh_tw"]} + row << t.join(";") + t = files.collect{|l|l.title_translations["en"]} + row << t.join(";") + t = files.collect{|l|l.title_translations["zh_tw"]} + row << t.join(";") + sheet.add_row row + end + + + + + +end \ No newline at end of file diff --git a/app/views/admin/event_news/feed.html.erb b/app/views/admin/event_news/feed.html.erb new file mode 100644 index 0000000..1824a0a --- /dev/null +++ b/app/views/admin/event_news/feed.html.erb @@ -0,0 +1,124 @@ +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag("admin/tags") %> +<% end %> +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "validator" %> +<% end %> + + + + + <% @table_feed_fields.each do |f| %> + <%= thead(f) %> + <% end %> + + + + <%= render :partial => "feed", :collection => @feeds %> + +
+<% if current_user.is_admin? or current_user.is_manager?(@module_app) %> + + + + +<% end %> + + +
\ No newline at end of file diff --git a/app/views/admin/event_news/import.html.erb b/app/views/admin/event_news/import.html.erb new file mode 100644 index 0000000..a337d89 --- /dev/null +++ b/app/views/admin/event_news/import.html.erb @@ -0,0 +1,87 @@ +<% content_for :page_specific_javascript do %> + +<% end %> +
+

<%= t("event_news.export_to_excel") %>

+ +

<%= t("event_news.import_from_excel") %>

+ <%= hidden_field_tag :authenticity_token, form_authenticity_token %> +
+ <% if @module_app.categories.count > 0 %> + +
+ +
+ + <%= t("event_news.please_create_tags_cats") %> +
+
+ <% else %> +
+
+

<%= t("event_news.create_atleast_one_cat") %>

+
+
+ <% end %> +
+ <% if @module_app.categories.count > 0 %> +
+ " class="btn btn-primary"> +
+ <% end %> +
+ + + +
+

<%= t("event_news.import_from_wp_xml") %>

+ <%= hidden_field_tag :authenticity_token, form_authenticity_token %> +
+
+ +
+ +
+
+
+
+ " class="btn btn-primary"> +
+
+ + \ No newline at end of file diff --git a/app/views/admin/event_news/index.html.erb b/app/views/admin/event_news/index.html.erb new file mode 100644 index 0000000..bc59a0e --- /dev/null +++ b/app/views/admin/event_news/index.html.erb @@ -0,0 +1,34 @@ +<%= render_filter @filter_fields, "index_table" %> + + <%= render 'index'%> + + +<%= render 'layouts/delete_modal', delete_options: @delete_options %> + +<% if EventNewsSetting.is_pro? && user_can_approve? %> + <%= render :partial=> "approval_modal" %> + + +<% end %> \ No newline at end of file diff --git a/app/views/admin/event_news/new.html.erb b/app/views/admin/event_news/new.html.erb new file mode 100644 index 0000000..dd33e29 --- /dev/null +++ b/app/views/admin/event_news/new.html.erb @@ -0,0 +1,5 @@ +<%= form_for @event_news, url: admin_event_news_index_path, html: {class: "form-horizontal main-forms previewable"} do |f| %> +
+ <%= render :partial => 'form', locals: {f: f} %> +
+<% end %> \ No newline at end of file diff --git a/app/views/admin/event_news/settings.html.erb b/app/views/admin/event_news/settings.html.erb new file mode 100644 index 0000000..c4bedcb --- /dev/null +++ b/app/views/admin/event_news/settings.html.erb @@ -0,0 +1,388 @@ +<%= stylesheet_link_tag "select2/select2" %> +<%= javascript_include_tag 'validator' %> +<%= javascript_include_tag "select2/select2.min" %> +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag "lib/main-forms" %> +<% end %> + +<% + sub_managers = @module_app.sub_managers + sub_managers.delete(nil) + all_statuses = [[t('top'),'is_top'],[t('hot'),'is_hot']] + tp1 = select_tag("event_news_setting[anns_status_settings][-1][status]",options_for_select(all_statuses)) + tp2 = select_tag("event_news_setting[anns_status_settings][-1][role_id]",options_for_select(Role.all.map{|r| [r.title,r.id]})) + tp3 = number_field_tag("event_news_setting[anns_status_settings][-1][top_limit]",nil, min: 0,required: true) + tp4 = "" + all_tp = "
#{tp1}
#{tp2}
#{tp3}
#{tp4}
" +%> + +
<%= t("event_news.click_on_submit") %>
+<%= form_for @setting, url: (@setting.new_record? ? admin_event_news_createsettings_path : admin_event_news_updatesettings_path), html: {class: "form-horizontal main-forms"} do |f| %> +
+
+ <%= f.label :only_manager_can_edit_status, t("event_news.only_manager_can_edit_status"), :class => "control-label muted" %> +
+ <%= f.check_box :only_manager_can_edit_status %> +
+
+
+ <%= f.label :is_display_edit_only, t("event_news.is_display_edit_only"), :class => "control-label muted" %> +
+ <%= f.check_box :is_display_edit_only %> +
+
+
+ <%= f.label :top_limit, t("event_news.top_limit"), :class => "control-label muted" %> +
+ <%= f.number_field :top_limit, :min => "0" %> + <%= t("event_news.for_unlimited") %> +
+
+
+
+
+
+ <%= t('status') %> +
+
+ <%= t('role') %> +
+
+ <%= t('event_news.top_limit') %> +
+
+ <% (EventNewsSetting.first.anns_status_settings rescue []).each_with_index do |v,i| %> +
+ <%= hidden_field_tag("event_news_setting[anns_status_settings][#{i}][_id]",v.id) %> +
+ <%= select_tag("event_news_setting[anns_status_settings][#{i}][status]",options_for_select(all_statuses,:selected => v['status'])) %> +
+
+ <%= select_tag("event_news_setting[anns_status_settings][#{i}][role_id]",options_for_select(Role.all.map{|r| [r.title,r.id]},:selected => v['role_id'])) %> +
+
+ <%= number_field_tag("event_news_setting[anns_status_settings][#{i}][top_limit]",v['top_limit'], min: 0,required: true) %> +
+
+ +
+
+ <% end %> +
+
+ +
+
+
+
+ <% if EventNewsSetting.is_pro? %> + <% if !sub_managers.blank? %> +
+ <%= f.label "Approver Setting", :class => "control-label muted" %> +
+ <%= t("event_news.approvers_list") %> + <%= @setting.approvers.count %> +
+
+ <% else %> + + <% end %> +
+ <%= f.label "Send emails to", :class => "control-label muted" %> +
+ > <%= t("admin") %> + > <%= t("manager") %> + > <%= t("event_news.approver") %> +
+
+
+
+ <% sub_managers.each do |sm| %> + <% if @setting.approvers.include?(sm.id.to_s) %> + + <% end %> + <% end %> +
+<% end %> +
+ <%= f.submit t('submit'), class: 'btn btn-primary' %> +
+<% end %> +
+<% if EventNewsSetting.is_pro? %> + + +<% end %> +<%= fields_for :iframe do |f| %> +
+
+ <%=t('event_news.event_news_setting_for_iframe')%> +
+ <%= f.label :layout_type, t("event_news.layout_type"), :class => "control-label muted" %> +
+ <% @layout_types = get_layouts(@module_app.key) %> + <% if @layout_types.first.kind_of?(Hash) %> + + + <% else %> + <%= f.select(:layout, @layout_types) %> + <% end %> +
+
+
+ <%= f.label :tags, t(:tags), :class => "control-label muted" %> +
+ <% @module_app.tags.each_with_index do |t,index| %> + + <% end %> +
+
+
+ +
+ <% @module_app.categories.each_with_index do |c,index| %> + + <% end %> +
+
+
+ <%= f.label :authors, t('event_news.table.author'), :class => "control-label muted" %> +
+ <%= render partial: 'admin/members/generate_modal_select' , locals: { :@sorted_members => @sorted_members ,:member_form_id => "card-list-members",:member_field_name=>"iframe[member_ids][]" } %> +
+
+
+ <%= f.label :show_page, t('event_news.show_page'), :class => "control-label muted" %> +
+ <%=f.check_box :show_page ,{:checked=>'checked'},'true','false'%> +
+
+
+ <%= f.label :data_count, t(:data_count), :class => "control-label muted" %> +
+ <%=f.number_field :data_count, {min: 0,:value=> 10} %> +
+
+ +
+
+<% end %> + \ No newline at end of file diff --git a/app/views/email/event_news_email.html.erb b/app/views/email/event_news_email.html.erb new file mode 100644 index 0000000..902acf0 --- /dev/null +++ b/app/views/email/event_news_email.html.erb @@ -0,0 +1 @@ +<%= @data["html"].html_safe %> \ No newline at end of file diff --git a/app/views/email/reapproval_event_news_email.html.erb b/app/views/email/reapproval_event_news_email.html.erb new file mode 100644 index 0000000..bc8d330 --- /dev/null +++ b/app/views/email/reapproval_event_news_email.html.erb @@ -0,0 +1,3 @@ +

Hello <%= @data["name"] %>,

+

<%= @data["submitter"] %> <%= t("event_news.updated_annoucement") %> +<%= t("event_news.click_here_to_see") %> \ No newline at end of file diff --git a/app/views/email/rejection_email.html.erb b/app/views/email/rejection_email.html.erb new file mode 100644 index 0000000..fe516d5 --- /dev/null +++ b/app/views/email/rejection_email.html.erb @@ -0,0 +1,3 @@ +

Hello <%= @data["name"] %>,

+

<%= @data["rejector"] %> <%= t("event_news.rejected_event_news") %> : <%= @data["reason"].nil? || @data["reason"] == "" ? "" : "#{@data["reason"]}" %>

+<%= t("event_news.click_here_to_see") %> \ No newline at end of file diff --git a/app/views/event_news/email.html.erb b/app/views/event_news/email.html.erb new file mode 100644 index 0000000..f9f7f5f --- /dev/null +++ b/app/views/event_news/email.html.erb @@ -0,0 +1,19 @@ + + + + + + +
+ + <%= t('event_news.mail_hi') %>

+ <%= t('event_news.mail_url_view') %>

+ " target="_blank"> <%= @data["title"] %>

+ + --
+ <%= t('event_news.mail_source') %> :" target="_blank"> <%= Site.first.title %>
+ <%= t('event_news.mail_time') %> <%= DateTime.now %> +
+ + + \ No newline at end of file diff --git a/app/views/event_news/index.html.erb b/app/views/event_news/index.html.erb new file mode 100644 index 0000000..c27d2b2 --- /dev/null +++ b/app/views/event_news/index.html.erb @@ -0,0 +1,85 @@ +<% params = OrbitHelper.params + page = Page.where(url:params['url']).first + enable_search_flag = false + if page.methods.include? 'select_option_items'.to_sym + ModuleApp.all.select{|tmp| tmp.key.to_s=='event_news'}.each do |modile_app| + @show_option_items = modile_app.show_option_items rescue nil + end + page.select_option_items.each do |select_option_item| + if !(@show_option_items.nil?) && select_option_item.field_name == @show_option_items.keys[1].to_s + value = YAML.load(select_option_item.value) + if value[I18n.locale] == t('event_news.yes') + enable_search_flag = true + end + end + end + end +%> +<% if enable_search_flag %> + +
+ <% cats = Array(page.categories) + if cats.include? 'all' + cats = ModuleApp.where(key: 'event_news').first.categories + else + cats = cats.map{|v| Category.where(id: v).first}.compact + end + all_cat = [[t('event_news.all'),'all']] + %> +
+ <%= select_tag('category',options_for_select(all_cat.concat(cats.map{|v| [v.title,v.id.to_s]}),:selected => params['category'].to_s),:id=>"category_select_box",:prompt => t('event_news.select_prompt')) %> + " placeholder="<%= t('event_news.keywords') %>"> +
+
+ " placeholder="<%= t('event_news.stime') %>" data-format="yyyy/mm/dd"> +
+ ~ +
+ " placeholder="<%= t('event_news.etime') %>" data-format="yyyy/mm/dd"> +
+
+ + +
+
+<% end %> +<%= render_view %> \ No newline at end of file diff --git a/app/views/event_news/show.html.erb b/app/views/event_news/show.html.erb new file mode 100644 index 0000000..00eec08 --- /dev/null +++ b/app/views/event_news/show.html.erb @@ -0,0 +1,76 @@ +<% + require 'event_news_helper' + params = OrbitHelper.params + page = Page.where(url:params['url']).first + @show_back_and_next_flag = 0 + if page.methods.include? 'select_option_items'.to_sym + ModuleApp.all.select{|tmp| tmp.key.to_s=='event_news'}.each do |modile_app| + @show_option_items = modile_app.show_option_items rescue nil + end + page.select_option_items.each do |select_option_item| + if !(@show_option_items.nil?) && select_option_item.field_name == @show_option_items.keys.first.to_s + value = YAML.load(select_option_item.value) + tmp = value[:en] + I18n.with_locale(:en) do + if tmp == t('event_news.not_show') + @show_back_and_next_flag = 0 + elsif tmp == t('event_news.show_top') + @show_back_and_next_flag = 1 + elsif tmp == t('event_news.show_bottom') + @show_back_and_next_flag = 2 + end + end + end + end + end + if @show_back_and_next_flag != 0 + uid = params['uid'] + sorted,total_pages = get_sorted_annc(0) + now_index = sorted.to_enum.with_index.select{|v| v[0].uid==uid}[0][1] rescue nil + if !now_index.nil? + if now_index != 0 + prev_result = sorted[now_index-1] + prev_url = params['url'] + '/' + prev_result.to_param + prev_content = "" + end + if now_index != sorted.length-1 + next_result = sorted[now_index+1] + next_url = params['url'] + '/' + next_result.to_param + next_content = "" + end + content = "
#{prev_content}#{next_content}
".html_safe + else + content = '' + end + end +%> +<% if @show_back_and_next_flag!=0 %> + +<% end %> + +<% if @show_back_and_next_flag==1 %> +<%= content %> +<% end %> +<%= render_view %> +<% if @show_back_and_next_flag==2 %> +<%= content %> +<% end %> \ No newline at end of file diff --git a/app/views/event_news/show_widget.html.erb b/app/views/event_news/show_widget.html.erb new file mode 100644 index 0000000..770d885 --- /dev/null +++ b/app/views/event_news/show_widget.html.erb @@ -0,0 +1,15 @@ + + + + <%= render_site_title %> + <%= stylesheet_link_tag "//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css"%> + <%= stylesheet_link_tag "event_news/bootstrap/bootstrap.min.css"%> + <%= stylesheet_link_tag "template/template"%> + <%= javascript_include_tag "jquery.min"%> + <%= javascript_include_tag "bootstrap.min"%> + + + <% @target_action = "show_widget" %> + <%=render_view_for_annc((!params[:layout_type].blank? ? params[:layout_type] : 'annc_index1'))%> + + \ No newline at end of file diff --git a/app/views/event_news_feeds/rssfeed.rss.builder b/app/views/event_news_feeds/rssfeed.rss.builder new file mode 100644 index 0000000..1b6323a --- /dev/null +++ b/app/views/event_news_feeds/rssfeed.rss.builder @@ -0,0 +1,16 @@ +xml.instruct! :xml, :version => "1.0" +xml.rss :version => "2.0" do + xml.channel do + xml.title @bf.title + xml.link "/xhr/event_news/rssfeed/#{params[:uid]}.rss" + + for e in @event_news + xml.item do + xml.title e.title + xml.description e.subtitle + xml.pubDate e.created_at.to_s(:rfc822) + xml.link page_for_event_news(e) + end + end + end +end \ No newline at end of file diff --git a/bin/rails b/bin/rails new file mode 100644 index 0000000..08ba0ad --- /dev/null +++ b/bin/rails @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application. + +ENGINE_ROOT = File.expand_path('../..', __FILE__) +ENGINE_PATH = File.expand_path('../../lib/announcement/engine', __FILE__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +# require 'rails/all' +# require 'rails/engine/commands' +require "action_controller/railtie" +require "action_mailer/railtie" +require "sprockets/railtie" +require "rails/test_unit/railtie" +require 'rails/engine/commands' +require "mongoid/railtie" diff --git a/config/initializers/scheduler.rb b/config/initializers/scheduler.rb new file mode 100644 index 0000000..24f6666 --- /dev/null +++ b/config/initializers/scheduler.rb @@ -0,0 +1,9 @@ +require 'rufus-scheduler' + +scheduler = Rufus::Scheduler.new + +#return if defined?(Rails::Console) || Rails.env.test? || File.split($0).last == 'rake' + +scheduler.cron '43 2 * * *' do + system('bundle exec rake bulletin:remove_preview_bulletins') +end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..a72cd9d --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,134 @@ +en: + module_name: + event_news: Event News + event_news: + notes: Notes + speaker: Speaker + host: Host + event_date: Event Date + start_date: Start date + end_date: End date + add_to_calendar: Add to calendar + blank_to_set: (blank to use event news setting) + stime: start time + etime: end time + select_prompt: --select category-- + all: All + keywords: Keywords + enable_search: Enable search feature + 'yes': 'Yes' + 'no': 'No' + image: Cover Image + picture_showing_size: Picture Showing Size + orignal_size: Original Size + small_size: Small Size + medium_size: Medium Size + showing_back_and_next: Show back and next + not_show: Not show + show_top: Show at top + show_bottom: Show at bottom + prev: previous + next: next + table: + title : Title + date : Date + status : Status + sub_title: Sub Title + category: Category + author: Author + link: Link + file: File + view_count: View Count + department: Department + add_new: Add New + export_to_excel: Export to Excel + export_all_anns: Export all Event News + import_from_excel: Import from Excel + download_example_sheet_here: Download example sheet here + please_create_tags_cats: Please create all the tags and categories before hand. Only excel file is allowed + create_atleast_one_cat: Please create atleast one category before importing. + import_from_wp_xml: Import from WordPress XML + click_on_submit: Click on Submit to save the changes + approvers_list: Approvers List + click_set_sub_manager: Click here to set Sub Managers for this module + approver: Approver + top_limit: Top Limit + for_unlimited: Put 0 for unlimited + feed_name: Feed Name + rssfeed: RSS Feed Link + jsonfeed: JSON Feed Link + feed_list: Feed List + approve: Approve + all_articles: All Articles + settings: Settings + import: Import / Export + event_news_module: Event News + approval_setting: Approval Setting + approve_event_news_fail: Approval Fail + approve_event_news_success: Approve Successfully + approval_waiting: Approval + submitted_new_event_news: "%{poster} submitted a new event news waiting for your approval." + click_here_to_see: Please click the link below to view the event news. + rejected_annoucement: has rejected your event news, because + updated_annoucement: "%{poster} updated the rejected event news." + event_news_subject: New event news waiting for approval + approval_site: Site + approval_mail_hi: Hello %{name}, + approval_event_news_title: Event News Title + event_news: Event News + categories: Categories + create_event_news_success: Create Bulletin Successfully + create_event_news_category_success: Create Category Successfully + date: Event News Date + default_widget: + event_news_category_with_title: Bulletin Category with Title + postdate: Post Date + subtitle: Subtitle + title: Title + editing_event_news: Edit event news + editing_event_news_category: Edit Category + file: Attachment + file_description: File Description + file_name: File Name + frontend: + event_news: Event News front-end + search_result: Search result + link_name: Link Name + new_event_news_category: New Bulletin Category + picture: Cover Picture + search: Search + selected_file: Select File + update_event_news_category_success: Update Category Successfully + url: URL + widget: + event_news_and_web_links: Differential Nav. + index: Index + search: Search + more: More + email_reminder: Email Reminder + activate_email_reminder: Activate Email Reminder + email_sentdate: Email Time + email_to: Email To + mail_subject: this is an event news reminder from【%{site_title}】 + view_count: View Counts + other_mailaddress: Other Email + other_mailaddress_note: Divide different email accounts with "," + mail_hi: Hi + mail_url_view: This email is the reminder of an event news, please click the link for the details + mail_source: Source + mail_time: Time + image_upload_size_note: The following recommendations %{image_upload_size} upload size + resend_mail: Re-send Email + is_external_link: Enable External Link + external_link: External Link + external_link_hint: "Make sure URL starts with http://" + display_subtitle: Display Subtitle in Content Page + display_img: Display Cover Image in Content Page + is_display_edit_only: Only display editable event news + only_manager_can_edit_status: Only manager can edit status of event news + layout_type: Layout type + event_news_setting_for_iframe: Event News settings for iframe + url_generate: Url Generate + show_page: Show pagination + URL: URL + copy: Copy diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml new file mode 100644 index 0000000..2d829f6 --- /dev/null +++ b/config/locales/zh_tw.yml @@ -0,0 +1,137 @@ +zh_tw: + module_name: + event_news: 活動公告 + event_news: + notes: 備註 + speaker: 演講者 + host: 主持人 + event_date: 事件日期 + start_date: 公告日期 + end_date: 下架日期 + add_to_calendar: 加入行事曆 + blank_to_set: (留白則使用公告設定) + stime: 開始時間 + etime: 結束時間 + select_prompt: --選取類別-- + all: 全部 + keywords: 關鍵字 + enable_search: 開啟搜尋功能 + 'yes': 是 + 'no': 否 + image: 封面圖片 + picture_showing_size: 圖片顯示大小 + orignal_size: 原圖大小 + small_size: 小張縮圖 + medium_size: 中等縮圖 + showing_back_and_next: 顯示上下則 + not_show: 不顯示 + show_top: 顯示在最上面 + show_bottom: 顯示在最下面 + prev: 上一則 + next: 下一則 + table: + title : 標題 + date : 張貼日期 + status : 標籤 + sub_title: 副標題 + category: 類別 + author: 張貼人 + link: 超連結 + file: 檔案下載 + view_count: 瀏覽人次 + department: 單位 + add_new: 新建 + import: 匯入 + export_to_excel: 匯出至Excel檔 + export_all_anns: 匯出所有活動公告 + import_from_excel: 從Excel檔匯入 + download_example_sheet_here: 在此下載範例 + please_create_tags_cats: 甲、 請事先建立所有標籤及分類。 僅限Excel檔。 + create_atleast_one_cat: 匯入前, 請先建立至少一個類別 + import_from_wp_xml: 從WordPress XML檔匯入 + top_limit: 最高設限 + for_unlimited: 歸零不設限 + click_on_submit: 點"提交"儲存變更 + approvers_list: 審核人名單 + click_set_sub_manager: 點這邊來設定這個模組的副管理者 + approver: 審核人 + approve: 通過 + feed_name: Feed 標題 + settings: 設定 + import: 匯入 / 匯出 + rssfeed: RSS 供給連結 + jsonfeed: JSON 供給連結 + feed_list: 訂閱清單 + all_articles: 文章列表 + event_news_module: 活動公告 + approval_setting: 審核設定 + approve_event_news_fail: 審核失敗 + approve_event_news_success: 審核成功 + approval_waiting: 審核 + submitted_new_announcement: 貴單位於全球資訊網有一則 %{poster} 張貼的最新消息待您審核發布, + click_here_to_see: 請您點擊以下網址,前往審核 + rejected_annoucement: 未通過您的公告審核,原因為 + updated_annoucement: 貴單位於全球資訊網有一則 %{poster} 被拒絕的最新消息已重新編輯待您審核發布, + announcement_subject: 系統訊息 - 最新消息內容審核通知 + approval_mail_hi: 親愛的 %{name} 主管您好 + approval_site: 網址 + approval_announcement_title: 消息標題 + event_news: 活動公告 + categories: 類別 + create_event_news_success: 建立公告成功 + create_event_news_category_success: 建立類別成功 + date: 起迄日期 + default_widget: + event_news_category_with_title: 公告類別及標題 + postdate: 張貼日期 + subtitle: 副標題 + title: 標題 + editing_announcement: 編輯類別 + editing_announcement_category: 編輯類別 + error: + no_avilb_cate_for_posting: 沒有可以張貼的類別 + file: 附加檔案 + file_description: 檔案描述 + file_name: 檔案名稱 + frontend: + event_news: 公告前台 + search_result: 搜尋結果頁 + link_name: 連結名稱 + new_event_news_category: 新增公告類別 + picture: 刊頭圖片 + search: 搜尋 + selected_file: 選擇檔案 + update_event_news_category_success: 更新類別成功 + url: 連結位置 + widget: + event_news_and_web_links: 分眾頁籤 + index: 索引 + search: 搜尋 + more: 更多+ + email_reminder: 寄送提醒 + activate_email_reminder: 開啟寄送提醒 + email_sentdate: 寄送時間 + email_to: 寄送對象 + view_count: 瀏覽人次 + other_mailaddress: 其他Mail + other_mailaddress_note: 輸入多組mail時,請用","逗號隔開 + mail_subject: 來自【%{site_title}】的公告事件提醒 + mail_hi: 您好 + mail_url_view: 此封信件為活動公告事件提醒,請點選以下連結詳細觀看 + mail_source: 來源 + mail_time: 時間 + image_upload_size_note: 建議檔案小於%{image_upload_size} + resend_mail: 重新寄送提醒 + is_external_link: 連結外部網址 + external_link: 外部連結 + external_link_hint: "確定連結開頭為http://" + display_subtitle: 內容頁顯示副標題 + display_img: 內容頁顯示封面圖片 + is_display_edit_only: 只顯示可更新的活動公告 + only_manager_can_edit_status: 只有管理者可更新活動公告狀態 + layout_type: 頁面樣式 + event_news_setting_for_iframe: 活動公告iframe設定 + url_generate: 網址生成 + show_page: 顯示頁碼 + URL: 網址 + copy: 複製 \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..c590180 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,41 @@ +Rails.application.routes.draw do + + locales = Site.first.in_use_locales rescue I18n.available_locales + + scope "(:locale)", locale: Regexp.new(locales.join("|")) do + namespace :admin do + post 'event_news/preview', to: 'event_news#preview' + post 'event_news/createfeed', to: 'event_news#createfeed' + post 'event_news/importanns', to: 'event_news#importanns' + post 'event_news/import_from_xml', to: 'event_news#import_from_xml' + get 'event_news/excel_format', to: 'event_news#excel_format' + get 'event_news/export_excel', to: 'event_news#export_excel' + patch 'event_news/updatefeed', to: 'event_news#updatefeed' + delete 'event_news/deletefeed', to: 'event_news#deletefeed' + get 'event_news/destroy_preview/:slug_title-:uid', to: 'event_news#destroy_preview' + post 'event_news/approve_event_news', to: 'event_news#approve_event_news' + get 'event_news/feed', to: 'event_news#feed' + get 'event_news/feedform', to: 'event_news#feedform' + get 'event_news/settings', to: 'event_news#settings' + get 'event_news/import', to: 'event_news#import' + post 'event_news/createsettings', to: 'event_news#createsettings' + patch 'event_news/updatesettings', to: 'event_news#updatesettings' + post 'event_news/import_from_wp', to: 'event_news#import_from_wp' + post 'event_news/generate_iframe_url' => 'event_news#generate_iframe_url' + resources :event_news + end + + resources :event_news do + collection do + get ':slug_title-:uid', to: 'event_news#show', as: :display + end + end + + get "/xhr/event_news/feed/:uid" => "event_news_feeds#feed" + get "/xhr/event_news/rssfeed/:uid" => "event_news_feeds#rssfeed" + get "/xhr/event_news/feeds" => "event_news_feeds#feeds" + get '/xhr/event_news/event_news.json', to: 'event_news_module#get_event_news' + get '/xhr/panel/event_news/widget/sync_data' => 'event_news#show_widget' + end + +end diff --git a/event_news_mod.gemspec b/event_news_mod.gemspec new file mode 100644 index 0000000..14487a1 --- /dev/null +++ b/event_news_mod.gemspec @@ -0,0 +1,26 @@ +# encoding: UTF-8 +$:.push File.expand_path("../lib", __FILE__) + +# Maintain your gem's version: +require "event_news_mod/version" +env_pwd = ENV['PWD'] +app_path = File.expand_path(__dir__) +template_path = env_pwd + '/app/templates' +all_template = Dir.glob(template_path+'/*/') + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "event_news_mod" + s.version = EventNewsMod::VERSION + s.authors = ["RulingDigital"] + s.email = ["orbit@rulingcom.com"] + s.homepage = "http://www.rulingcom.com" + s.summary = "EventNews for Orbit" + s.description = "EventNews for Orbit" + s.license = "MIT" + + s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] + s.test_files = Dir["test/**/*"] + + s.add_dependency "rufus-scheduler", "~> 3.6.0" +end diff --git a/lib/event_news_mod.rb b/lib/event_news_mod.rb new file mode 100644 index 0000000..b9e62c4 --- /dev/null +++ b/lib/event_news_mod.rb @@ -0,0 +1,4 @@ +require "event_news_mod/engine" +module EventNewsMod + +end diff --git a/lib/event_news_mod/engine.rb b/lib/event_news_mod/engine.rb new file mode 100644 index 0000000..e48c604 --- /dev/null +++ b/lib/event_news_mod/engine.rb @@ -0,0 +1,117 @@ +require "yaml" +module EventNewsMod + class Engine < ::Rails::Engine + initializer "event_news" do + begin + translate_data = Dir["#{EventNewsMod::Engine.root}/config/locales/*.yml"] .map{|yaml_file| YAML.load(File.read(yaml_file))} + data = {} + key1 = {} + value1 = {} + value2 = {} + value3 = {} + data_item = {} + key_item1 = {} + key_item2 = {} + value_item1 = {} + value_item2 = {} + value_item3 = {} + value2_item1 = {} + value2_item2 = {} + translate_data.each do |t_data| + v = t_data.values + k = t_data.keys[0] + key1[k] = v[0]['event_news']['picture_showing_size'] + value1[k] = v[0]['event_news']['small_size'] + value2[k] = v[0]['event_news']['medium_size'] + value3[k] = v[0]['event_news']['orignal_size'] + key_item1[k] = v[0]['event_news']['showing_back_and_next'] + key_item2[k] = v[0]['event_news']['enable_search'] + value_item1[k] = v[0]['event_news']['not_show'] + value_item2[k] = v[0]['event_news']['show_bottom'] + value_item3[k] = v[0]['event_news']['show_top'] + value2_item1[k] = v[0]['event_news']['no'] + value2_item2[k] = v[0]['event_news']['yes'] + end + data[key1] = [value1,value2,value3] + data_item[key_item1] = [value_item1,value_item2,value_item3] + data_item[key_item2] = [value2_item1,value2_item2] + require File.expand_path('../../../app/models/event_news_cache', __FILE__) + if defined? EvenNewsCache + EvenNewsCache.destroy_all + end + rescue => e + puts ['error in event_news',e] + end + OrbitApp.registration "event_news", :type => "ModuleApp" do + module_label "event_news.event_news" + base_url File.expand_path File.dirname(__FILE__) + widget_methods ["widget","random_event_news_widget", "tag_cloud"] + widget_settings [{"data_count"=>30}] + taggable "EventNews" + categorizable + authorizable + frontend_enabled + feeds_url "/xhr/event_news/feeds" + data_count 1..30 + begin + show_options data + show_option_items data_item + rescue => e + puts ['there_was_no_show_option_method',e] + end + side_bar do + head_label_i18n 'event_news.event_news', icon_class: "icons-megaphone" + available_for "users" + active_for_controllers (['admin/event_news']) + head_link_path "admin_event_news_index_path" + + context_link 'event_news.all_articles', + :link_path=>"admin_event_news_index_path" , + :priority=>1, + :active_for_action=>{'admin/event_news'=>'index'}, + :available_for => 'users' + context_link 'new_', + :link_path=>"new_admin_event_news_path" , + :priority=>2, + :active_for_action=>{'admin/event_news'=>'new'}, + :available_for => 'sub_managers' + context_link 'categories', + :link_path=>"admin_module_app_categories_path" , + :link_arg=>"{:module_app_id=>ModuleApp.find_by(:key=>'event_news').id}", + :priority=>3, + :active_for_action=>{'admin/event_news'=>'categories'}, + :active_for_category => 'EventNewsModule', + :available_for => 'managers' + context_link 'tags', + :link_path=>"admin_module_app_tags_path" , + :link_arg=>"{:module_app_id=>ModuleApp.find_by(:key=>'event_news').id}", + :priority=>4, + :active_for_action=>{'admin/event_news'=>'tags'}, + :active_for_tag => 'EventNewsModule', + :available_for => 'managers' + context_link 'event_news.feed_list', + :link_path=>"admin_event_news_feed_path" , + :priority=>5, + :active_for_action=>{'admin/event_news'=>'feed'}, + :available_for => 'managers' + context_link 'event_news.import', + :link_path=>"admin_event_news_import_path" , + :priority=>6, + :active_for_action=>{'admin/event_news'=>'import'}, + :available_for => 'managers' + context_link 'event_news.settings', + :link_path=>"admin_event_news_settings_path" , + :priority=>6, + :active_for_action=>{'admin/event_news'=>'settings'}, + :available_for => 'managers' + end + + end + # temp = YAML.load_file(File.join(Rails.root,"config","mongoid.yml")) + # dbsettings = temp["production"]["sessions"]["default"] + # s = Moped::Session.new(dbsettings["hosts"]) + # s.use dbsettings["database"] + # s[:bulletins].indexes.create({expirable_created_at: 1},{ expireAfterSeconds: 180 }) + end + end +end \ No newline at end of file diff --git a/lib/event_news_mod/version.rb b/lib/event_news_mod/version.rb new file mode 100644 index 0000000..af93494 --- /dev/null +++ b/lib/event_news_mod/version.rb @@ -0,0 +1,3 @@ +module EventNewsMod + VERSION = "0.0.1" +end diff --git a/lib/event_news_model/cache.rb b/lib/event_news_model/cache.rb new file mode 100644 index 0000000..fff635f --- /dev/null +++ b/lib/event_news_model/cache.rb @@ -0,0 +1,16 @@ +module EventNewsModel + module Cache + require 'active_support/concern' + extend ActiveSupport::Concern + included do + before_save :do_before_save + end + def do_before_save + if self.class == SubPart + EventNewsCache.where(parent_id:self.id).destroy + elsif self.class == EventNews || (self.class == Page && self.module == "event_news") + EventNewsCache.all.destroy + end + end + end +end \ No newline at end of file diff --git a/lib/tasks/bulletin_tasks.rake b/lib/tasks/bulletin_tasks.rake new file mode 100644 index 0000000..434204a --- /dev/null +++ b/lib/tasks/bulletin_tasks.rake @@ -0,0 +1,8 @@ +desc 'Remove duplicated bulletins (announcements) created by preview' + +namespace :bulletin do + task :remove_preview_bulletins => [:environment] do + bulletins = Bulletin.where(is_preview: true) + bulletins.destroy_all + end +end diff --git a/modules/event_news/_event_news_widget1.html.erb b/modules/event_news/_event_news_widget1.html.erb new file mode 100644 index 0000000..5a029e4 --- /dev/null +++ b/modules/event_news/_event_news_widget1.html.erb @@ -0,0 +1,32 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget10.html.erb b/modules/event_news/_event_news_widget10.html.erb new file mode 100644 index 0000000..d4fa40e --- /dev/null +++ b/modules/event_news/_event_news_widget10.html.erb @@ -0,0 +1,22 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget11.html.erb b/modules/event_news/_event_news_widget11.html.erb new file mode 100644 index 0000000..8f8776d --- /dev/null +++ b/modules/event_news/_event_news_widget11.html.erb @@ -0,0 +1,22 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget12.html.erb b/modules/event_news/_event_news_widget12.html.erb new file mode 100644 index 0000000..ba4cfe5 --- /dev/null +++ b/modules/event_news/_event_news_widget12.html.erb @@ -0,0 +1,27 @@ +
+

+ {{widget-title}} +

+ + + + + + + + + + + + + +
{{title-head}}{{date-head}}
+ + {{status}} + + {{title}} +
+ +
\ No newline at end of file diff --git a/modules/event_news/_event_news_widget13.html.erb b/modules/event_news/_event_news_widget13.html.erb new file mode 100644 index 0000000..7daea9a --- /dev/null +++ b/modules/event_news/_event_news_widget13.html.erb @@ -0,0 +1,27 @@ +
+

+ {{widget-title}} +

+ + + + + + + + + + + + + +
{{date-head}}{{title-head}}
+ + {{status}} + + {{title}} +
+ +
\ No newline at end of file diff --git a/modules/event_news/_event_news_widget14.html.erb b/modules/event_news/_event_news_widget14.html.erb new file mode 100644 index 0000000..9fe446f --- /dev/null +++ b/modules/event_news/_event_news_widget14.html.erb @@ -0,0 +1,29 @@ +
+

+ {{widget-title}} +

+
+
+ {{main_picture_description}} +
+
    +
  • +
    +

    + + {{status}} + + {{title}} +

    + +
    +
  • +
+
+ +
diff --git a/modules/event_news/_event_news_widget15.html.erb b/modules/event_news/_event_news_widget15.html.erb new file mode 100644 index 0000000..538d8b9 --- /dev/null +++ b/modules/event_news/_event_news_widget15.html.erb @@ -0,0 +1,131 @@ +
+ +
+ + +
+ +
+ + diff --git a/modules/event_news/_event_news_widget16.html.erb b/modules/event_news/_event_news_widget16.html.erb new file mode 100644 index 0000000..a5f600c --- /dev/null +++ b/modules/event_news/_event_news_widget16.html.erb @@ -0,0 +1,30 @@ +
+ + + + + + + + + + + + + + + + + + + +
{{event_date-head}}{{speaker-head}}{{title-head}}{{host-head}}{{notes-head}}
{{speaker}} + + {{status}} + + {{title}} + {{host}}{{notes}}
+ +
\ No newline at end of file diff --git a/modules/event_news/_event_news_widget2.html.erb b/modules/event_news/_event_news_widget2.html.erb new file mode 100644 index 0000000..57480c6 --- /dev/null +++ b/modules/event_news/_event_news_widget2.html.erb @@ -0,0 +1,34 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget3.html.erb b/modules/event_news/_event_news_widget3.html.erb new file mode 100644 index 0000000..6568d63 --- /dev/null +++ b/modules/event_news/_event_news_widget3.html.erb @@ -0,0 +1,34 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget4.html.erb b/modules/event_news/_event_news_widget4.html.erb new file mode 100644 index 0000000..cde33cc --- /dev/null +++ b/modules/event_news/_event_news_widget4.html.erb @@ -0,0 +1,87 @@ +
+ + +
+ diff --git a/modules/event_news/_event_news_widget5.html.erb b/modules/event_news/_event_news_widget5.html.erb new file mode 100644 index 0000000..57805f4 --- /dev/null +++ b/modules/event_news/_event_news_widget5.html.erb @@ -0,0 +1,31 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget6.html.erb b/modules/event_news/_event_news_widget6.html.erb new file mode 100644 index 0000000..89ff872 --- /dev/null +++ b/modules/event_news/_event_news_widget6.html.erb @@ -0,0 +1,26 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget7.html.erb b/modules/event_news/_event_news_widget7.html.erb new file mode 100644 index 0000000..97852a3 --- /dev/null +++ b/modules/event_news/_event_news_widget7.html.erb @@ -0,0 +1,26 @@ +
+

+ {{widget-title}} +

+ + +
diff --git a/modules/event_news/_event_news_widget8.html.erb b/modules/event_news/_event_news_widget8.html.erb new file mode 100644 index 0000000..3c0d471 --- /dev/null +++ b/modules/event_news/_event_news_widget8.html.erb @@ -0,0 +1,29 @@ +
+

+ {{widget-title}} +

+ + + + + + + + + + + + + + + +
{{category-head}}{{title-head}}{{date-head}}
{{category}} + + {{status}} + + {{title}} +
+ +
\ No newline at end of file diff --git a/modules/event_news/_event_news_widget9.html.erb b/modules/event_news/_event_news_widget9.html.erb new file mode 100644 index 0000000..edde4ce --- /dev/null +++ b/modules/event_news/_event_news_widget9.html.erb @@ -0,0 +1,29 @@ +
+

+ {{widget-title}} +

+ + + + + + + + + + + + + + + +
{{date-head}}{{title-head}}{{category-head}}
+ + {{status}} + + {{title}} + {{category}}
+ +
\ No newline at end of file diff --git a/modules/event_news/event_news_index1.html.erb b/modules/event_news/event_news_index1.html.erb new file mode 100644 index 0000000..5db7c68 --- /dev/null +++ b/modules/event_news/event_news_index1.html.erb @@ -0,0 +1,25 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + +
{{category-head}}{{title-head}}{{date-head}}
{{category}} + + {{status}} + + {{title}} +
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index10.html.erb b/modules/event_news/event_news_index10.html.erb new file mode 100644 index 0000000..aeafbe2 --- /dev/null +++ b/modules/event_news/event_news_index10.html.erb @@ -0,0 +1,22 @@ +
+

{{page-title}}

+ > +
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index11.html.erb b/modules/event_news/event_news_index11.html.erb new file mode 100644 index 0000000..19543f6 --- /dev/null +++ b/modules/event_news/event_news_index11.html.erb @@ -0,0 +1,18 @@ +
+

{{page-title}}

+ +
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index12.html.erb b/modules/event_news/event_news_index12.html.erb new file mode 100644 index 0000000..1ac8abd --- /dev/null +++ b/modules/event_news/event_news_index12.html.erb @@ -0,0 +1,18 @@ +
+

{{page-title}}

+ +
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index13.html.erb b/modules/event_news/event_news_index13.html.erb new file mode 100644 index 0000000..65741a2 --- /dev/null +++ b/modules/event_news/event_news_index13.html.erb @@ -0,0 +1,23 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + +
{{title-head}}{{date-head}}
+ + {{status}} + + {{title}} +
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index14.html.erb b/modules/event_news/event_news_index14.html.erb new file mode 100644 index 0000000..62ac229 --- /dev/null +++ b/modules/event_news/event_news_index14.html.erb @@ -0,0 +1,23 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + +
{{date-head}}{{title-head}}
+ + {{status}} + + {{title}} +
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index15.html.erb b/modules/event_news/event_news_index15.html.erb new file mode 100644 index 0000000..9b89112 --- /dev/null +++ b/modules/event_news/event_news_index15.html.erb @@ -0,0 +1,25 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + +
{{date-head}}{{title-head}}{{view-count-head}}
+ + {{status}} + + {{title}} + {{view_count}}
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index16.html.erb b/modules/event_news/event_news_index16.html.erb new file mode 100644 index 0000000..8dd407d --- /dev/null +++ b/modules/event_news/event_news_index16.html.erb @@ -0,0 +1,39 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + + + +
{{date-head}}{{title-head}}{{link-head}}{{file-head}}
+ + {{status}} + + {{title}} + + +
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index17.html.erb b/modules/event_news/event_news_index17.html.erb new file mode 100644 index 0000000..c4c025d --- /dev/null +++ b/modules/event_news/event_news_index17.html.erb @@ -0,0 +1,27 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + + + +
{{category-head}}{{title-head}}{{date-head}}{{department-head}}
{{category}} + + {{status}} + + {{title}} + {{department}}
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index18.html.erb b/modules/event_news/event_news_index18.html.erb new file mode 100644 index 0000000..e901c47 --- /dev/null +++ b/modules/event_news/event_news_index18.html.erb @@ -0,0 +1,29 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + + + + + +
{{event_date-head}}{{speaker-head}}{{title-head}}{{host-head}}{{notes-head}}
{{speaker}} + + {{status}} + + {{title}} + {{host}}{{notes}}
+
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index2.html.erb b/modules/event_news/event_news_index2.html.erb new file mode 100644 index 0000000..e22a9c2 --- /dev/null +++ b/modules/event_news/event_news_index2.html.erb @@ -0,0 +1,27 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + + + +
{{category-head}}{{title-head}}{{date-head}}{{view-count-head}}
{{category}} + + {{status}} + + {{title}} + {{view_count}}
+
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index3.html.erb b/modules/event_news/event_news_index3.html.erb new file mode 100644 index 0000000..12d669e --- /dev/null +++ b/modules/event_news/event_news_index3.html.erb @@ -0,0 +1,25 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + +
{{date-head}}{{title-head}}{{category-head}}
+ + {{status}} + + {{title}} + {{category}}
+
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index4.html.erb b/modules/event_news/event_news_index4.html.erb new file mode 100644 index 0000000..3c646bf --- /dev/null +++ b/modules/event_news/event_news_index4.html.erb @@ -0,0 +1,27 @@ +
+

{{page-title}}

+ + + + + + + + + + + + + + + + + +
{{date-head}}{{title-head}}{{category-head}}{{view-count-head}}
+ + {{status}} + + {{title}} + {{category}}{{view_count}}
+
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index5.html.erb b/modules/event_news/event_news_index5.html.erb new file mode 100644 index 0000000..94cd17d --- /dev/null +++ b/modules/event_news/event_news_index5.html.erb @@ -0,0 +1,30 @@ +
+

{{page-title}}

+ +
+{{pagination_goes_here}} diff --git a/modules/event_news/event_news_index6.html.erb b/modules/event_news/event_news_index6.html.erb new file mode 100644 index 0000000..71fc4f8 --- /dev/null +++ b/modules/event_news/event_news_index6.html.erb @@ -0,0 +1,30 @@ +
+

{{page-title}}

+ +
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index7.html.erb b/modules/event_news/event_news_index7.html.erb new file mode 100644 index 0000000..3ade23c --- /dev/null +++ b/modules/event_news/event_news_index7.html.erb @@ -0,0 +1,83 @@ +
+

{{page-title}}

+ +
+{{pagination_goes_here}} + diff --git a/modules/event_news/event_news_index8.html.erb b/modules/event_news/event_news_index8.html.erb new file mode 100644 index 0000000..550ae02 --- /dev/null +++ b/modules/event_news/event_news_index8.html.erb @@ -0,0 +1,26 @@ +
+

{{page-title}}

+
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/event_news_index9.html.erb b/modules/event_news/event_news_index9.html.erb new file mode 100644 index 0000000..b3bb03d --- /dev/null +++ b/modules/event_news/event_news_index9.html.erb @@ -0,0 +1,22 @@ +
+

{{page-title}}

+ +
+{{pagination_goes_here}} \ No newline at end of file diff --git a/modules/event_news/info.json b/modules/event_news/info.json new file mode 100644 index 0000000..df7a3cb --- /dev/null +++ b/modules/event_news/info.json @@ -0,0 +1,278 @@ +{ + "frontend": [ + { + "filename" : "event_news_index1", + "name" : { + "zh_tw" : "1. 標準標題列表-1A ( 模組標題, 類別, 狀態, 標題, 日期 )", + "en" : "1. Standard Title List-1 (widget-title, category, status, title, postdate)" + }, + "thumbnail" : "event_news_index1_thumbs.png" + }, + { + "filename" : "event_news_index2", + "name" : { + "zh_tw" : "2. 標準標題列表-1B ( 模組標題, 類別, 狀態, 標題, 日期, 瀏覽人次 )", + "en" : "2. Standard Title List-1B (widget-title, category, status, title, postdate, view-count)" + }, + "thumbnail" : "event_news_index2_thumbs.png" + }, + { + "filename" : "event_news_index3", + "name" : { + "zh_tw" : "3. 標準表格列表-2A ( 模組標題, 日期, 狀態, 標題, 類別 )", + "en" : "3. Standard Table List-2 (widget-title, postdate, status, title, category)" + }, + "thumbnail" : "event_news_index3_thumbs.png" + }, + { + "filename" : "event_news_index4", + "name" : { + "zh_tw" : "4. 標準表格列表-2B ( 模組標題, 日期, 狀態, 標題, 類別, 瀏覽人次 )", + "en" : "4. Standard Table List-2 (widget-title, postdate, status, title, category, view-count)" + }, + "thumbnail" : "event_news_index4_thumbs.png" + }, + { + "filename" : "event_news_index5", + "name" : { + "zh_tw" : "5. 左圖右文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "5. Balanced Image + Text(Left) (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_index5_thumbs.png" + }, + { + "filename" : "event_news_index6", + "name" : { + "zh_tw" : "6. 右圖左文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "6. Balanced Image + Text(Right) (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_index6_thumbs.png" + }, + { + "filename" : "event_news_index7", + "name" : { + "zh_tw" : "7. 三欄圖文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "7. 3-Column Standard Image + Text (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_index7_thumbs.png" + }, + { + "filename" : "event_news_index8", + "name" : { + "zh_tw" : "8. 標準文字列表 ( 模組標題, 日期, 類別, 狀態, 標題, 副標題 )", + "en" : "8. Standard Text List (widget-title, postdate, category, status, title, subtitle)" + }, + "thumbnail" : "event_news_index8_thumbs.png" + }, + { + "filename" : "event_news_index9", + "name" : { + "zh_tw" : "9. 標準標題列表-1 ( 模組標題, 類別, 狀態, 標題, 日期 )", + "en" : "9. Standard Title List-1 (widget-title, category, status, title, postdate)" + }, + "thumbnail" : "event_news_index9_thumbs.png" + }, + { + "filename" : "event_news_index10", + "name" : { + "zh_tw" : "10. 標準標題列表-2 ( 模組標題, 日期, 狀態, 標題, 類別 )", + "en" : "10. Standard Title List-2 (widget-title, postdate, status, title, category)" + }, + "thumbnail" : "event_news_index10_thumbs.png" + }, + { + "filename" : "event_news_index11", + "name" : { + "zh_tw" : "11. 精簡標題列表-1 ( 模組標題, 狀態, 標題, 日期 )", + "en" : "11. Simple Title List-1 (widget-title, status, title, postdate)" + }, + "thumbnail" : "event_news_index11_thumbs.png" + }, + { + "filename" : "event_news_index12", + "name" : { + "zh_tw" : "12. 精簡標題列表-2 ( 模組標題, 日期, 狀態, 標題 )", + "en" : "12. Simple Title List-2 (widget-title, postdate, status, title)" + }, + "thumbnail" : "event_news_index12_thumbs.png" + }, + { + "filename" : "event_news_index13", + "name" : { + "zh_tw" : "13. 精簡表格列表-1 ( 模組標題, 狀態, 標題, 日期 )", + "en" : "13. Simple Table List (widget-title, status, title, postdate)" + }, + "thumbnail" : "event_news_index13_thumbs.png" + }, + { + "filename" : "event_news_index14", + "name" : { + "zh_tw" : "14. 精簡表格列表-2 ( 模組標題, 日期, 狀態, 標題 )", + "en" : "14. Simple Table List (widget-title, postdate, status, title)" + }, + "thumbnail" : "event_news_index14_thumbs.png" + }, + { + "filename" : "event_news_index15", + "name" : { + "zh_tw" : "15. 精簡表格列表-3 ( 模組標題, 日期, 狀態, 標題, 瀏覽人次 )", + "en" : "15. Simple Table List (widget-title, postdate, status, title, view-count)" + }, + "thumbnail" : "event_news_index15_thumbs.png" + }, + { + "filename" : "event_news_index16", + "name" : { + "zh_tw" : "16. 連結 + 附件表格列表 ( 模組標題, 類別, 狀態, 標題 )", + "en" : "16. Table List including Links and attachments (widget-title, category, status, title, view-count)" + }, + "thumbnail" : "event_news_index16_thumbs.png" + }, + { + "filename" : "event_news_index17", + "name" : { + "zh_tw" : "17. 標準標題列表-1A ( 類別, 標題, 日期, 張貼人 )", + "en" : "17. Standard Title List-1 ( category, title, postdate, department)" + }, + "thumbnail" : "event_news_index1_thumbs.png" + }, + { + "filename" : "event_news_index18", + "name" : { + "zh_tw" : "18. 標準標題列表-2 ( 日期, 演講者, 狀態, 標題, 主持人, 備註 )", + "en" : "18. Standard Title List-2 ( EventDate, speaker, status, title, host, notes)" + }, + "thumbnail" : "event_news_index1_thumbs.png" + } + ], + "widgets" : [ + { + "filename" : "event_news_widget1", + "name" : { + "zh_tw" : "1. 標準圖文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "1. Standard Image + Text (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_widget1_thumbs.png" + }, + { + "filename" : "event_news_widget2", + "name" : { + "zh_tw" : "2. 左圖右文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "2. Balanced Image + Text(Left) (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_widget2_thumbs.png" + }, + { + "filename" : "event_news_widget3", + "name" : { + "zh_tw" : "3. 右圖左文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "3. Balanced Image + Text(Right) (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_widget3_thumbs.png" + }, + { + "filename" : "event_news_widget4", + "name" : { + "zh_tw" : "4. 三欄圖文 ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "4. 3-Column Standard Image + Text (widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_widget4_thumbs.png" + }, + { + "filename" : "event_news_widget15", + "name" : { + "zh_tw" : "4.5. 三欄圖文-slide ( 模組標題, 圖片, 狀態, 日期, 類別, 標題, 副標題 )", + "en" : "4.5. 3-Column Standard Image + Text -slide(widget-title, image, status, postdate, category, title, subtitle)" + }, + "thumbnail" : "event_news_widget4_thumbs.png" + }, + { + "filename" : "event_news_widget5", + "name" : { + "zh_tw" : "5. 標準文字列表 ( 模組標題, 日期, 類別, 狀態, 標題, 副標題 )", + "en" : "5. Standard Text List (widget-title, postdate, category, status, title, subtitle)" + }, + "thumbnail" : "event_news_widget5_thumbs.png" + }, + { + "filename" : "event_news_widget6", + "name" : { + "zh_tw" : "6. 標準標題列表-1 ( 模組標題, 類別, 狀態, 標題, 日期 )", + "en" : "6. Standard Title List-1 (widget-title, category, status, title, postdate)" + }, + "thumbnail" : "event_news_widget6_thumbs.png" + }, + { + "filename" : "event_news_widget7", + "name" : { + "zh_tw" : "7. 標準標題列表-2 ( 模組標題, 日期, 狀態, 標題, 類別 )", + "en" : "7. Standard Title List-2 (widget-title, postdate, status, title, category)" + }, + "thumbnail" : "event_news_widget7_thumbs.png" + }, + { + "filename" : "event_news_widget8", + "name" : { + "zh_tw" : "8. 標準表格列表-1 ( 模組標題, 類別, 狀態, 標題, 日期 )", + "en" : "8. Standard Table List-1 (widget-title, category, status, title, postdate)" + }, + "thumbnail" : "event_news_widget8_thumbs.png" + }, + { + "filename" : "event_news_widget9", + "name" : { + "zh_tw" : "9. 標準表格列表-2 ( 模組標題, 日期, 狀態, 標題, 類別 )", + "en" : "9. Standard Table List-2 (widget-title, postdate, status, title, category)" + }, + "thumbnail" : "event_news_widget9_thumbs.png" + }, + { + "filename" : "event_news_widget10", + "name" : { + "zh_tw" : "10. 精簡標題列表-1 ( 模組標題, 狀態, 標題, 日期 )", + "en" : "10. Simple Title List-1 (widget-title, status, title, postdate)" + }, + "thumbnail" : "event_news_widget10_thumbs.png" + }, + { + "filename" : "event_news_widget11", + "name" : { + "zh_tw" : "11. 精簡標題列表-2 ( 模組標題, 日期, 狀態, 標題 )", + "en" : "11. Simple Title List-2 (widget-title, postdate, status, title)" + }, + "thumbnail" : "event_news_widget11_thumbs.png" + }, + { + "filename" : "event_news_widget12", + "name" : { + "zh_tw" : "12. 精簡表格列表-1 ( 模組標題, 狀態, 標題, 日期 )", + "en" : "12. Simple Table List (widget-title, status, title, postdate)" + }, + "thumbnail" : "event_news_widget12_thumbs.png" + }, + { + "filename" : "event_news_widget13", + "name" : { + "zh_tw" : "13. 精簡表格列表-2 ( 模組標題, 日期, 狀態, 標題 )", + "en" : "13. Simple Table List (widget-title, postdate, status, title)" + }, + "thumbnail" : "event_news_widget13_thumbs.png" + }, + { + "filename" : "event_news_widget14", + "name" : { + "zh_tw" : "14. 一圖 + 標題列表 ( 模組標題, 圖片, 狀態, 標題, 日期 )", + "en" : "14. 1 Image + Title List (widget-title, image, status, title, postdate)" + }, + "thumbnail" : "event_news_widget14_thumbs.png" + }, + { + "filename" : "event_news_widget16", + "name" : { + "zh_tw" : "15. 標準表格列表-3 ( 日期, 演講者, 狀態, 標題, 主持人, 備註 )", + "en" : "15. Standard Table List (EventDate, speaker, status, title, host, notes)" + }, + "thumbnail" : "event_news_widget13_thumbs.png" + } + ] +} \ No newline at end of file diff --git a/modules/event_news/show.html.erb b/modules/event_news/show.html.erb new file mode 100644 index 0000000..ce54291 --- /dev/null +++ b/modules/event_news/show.html.erb @@ -0,0 +1,75 @@ +
+

{{title}}

+ + + +
+

{{body}}

+
+
+
+

{{notes}}

+
+ + +
+ +{{link_to_edit}} + + \ No newline at end of file diff --git a/modules/event_news/thumbs/event_news_index10_thumbs.png b/modules/event_news/thumbs/event_news_index10_thumbs.png new file mode 100644 index 0000000..0745dc6 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index10_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index11_thumbs.png b/modules/event_news/thumbs/event_news_index11_thumbs.png new file mode 100644 index 0000000..8dc2261 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index11_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index12_thumbs.png b/modules/event_news/thumbs/event_news_index12_thumbs.png new file mode 100644 index 0000000..2e00654 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index12_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index13_thumbs.png b/modules/event_news/thumbs/event_news_index13_thumbs.png new file mode 100644 index 0000000..82eee2c Binary files /dev/null and b/modules/event_news/thumbs/event_news_index13_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index14_thumbs.png b/modules/event_news/thumbs/event_news_index14_thumbs.png new file mode 100644 index 0000000..0a58044 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index14_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index15_thumbs.png b/modules/event_news/thumbs/event_news_index15_thumbs.png new file mode 100644 index 0000000..cb9ed5e Binary files /dev/null and b/modules/event_news/thumbs/event_news_index15_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index16_thumbs.png b/modules/event_news/thumbs/event_news_index16_thumbs.png new file mode 100644 index 0000000..6ecaa4e Binary files /dev/null and b/modules/event_news/thumbs/event_news_index16_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index1_thumbs.png b/modules/event_news/thumbs/event_news_index1_thumbs.png new file mode 100644 index 0000000..0ad29c4 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index1_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index2_thumbs.png b/modules/event_news/thumbs/event_news_index2_thumbs.png new file mode 100644 index 0000000..d7baca7 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index2_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index3_thumbs.png b/modules/event_news/thumbs/event_news_index3_thumbs.png new file mode 100644 index 0000000..0193f81 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index3_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index4_thumbs.png b/modules/event_news/thumbs/event_news_index4_thumbs.png new file mode 100644 index 0000000..7c0a551 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index4_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index5_thumbs.png b/modules/event_news/thumbs/event_news_index5_thumbs.png new file mode 100644 index 0000000..832fe35 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index5_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index6_thumbs.png b/modules/event_news/thumbs/event_news_index6_thumbs.png new file mode 100644 index 0000000..eac8619 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index6_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index7_thumbs.png b/modules/event_news/thumbs/event_news_index7_thumbs.png new file mode 100644 index 0000000..b69abd9 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index7_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index8_thumbs.png b/modules/event_news/thumbs/event_news_index8_thumbs.png new file mode 100644 index 0000000..cf6eb30 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index8_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_index9_thumbs.png b/modules/event_news/thumbs/event_news_index9_thumbs.png new file mode 100644 index 0000000..9fc7c23 Binary files /dev/null and b/modules/event_news/thumbs/event_news_index9_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget10_thumbs.png b/modules/event_news/thumbs/event_news_widget10_thumbs.png new file mode 100644 index 0000000..8dc2261 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget10_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget11_thumbs.png b/modules/event_news/thumbs/event_news_widget11_thumbs.png new file mode 100644 index 0000000..2e00654 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget11_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget12_thumbs.png b/modules/event_news/thumbs/event_news_widget12_thumbs.png new file mode 100644 index 0000000..82eee2c Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget12_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget13_thumbs.png b/modules/event_news/thumbs/event_news_widget13_thumbs.png new file mode 100644 index 0000000..0a58044 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget13_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget14_thumbs.png b/modules/event_news/thumbs/event_news_widget14_thumbs.png new file mode 100644 index 0000000..d1cab18 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget14_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget1_thumbs.png b/modules/event_news/thumbs/event_news_widget1_thumbs.png new file mode 100644 index 0000000..77ba0a8 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget1_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget2_thumbs.png b/modules/event_news/thumbs/event_news_widget2_thumbs.png new file mode 100644 index 0000000..832fe35 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget2_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget3_thumbs.png b/modules/event_news/thumbs/event_news_widget3_thumbs.png new file mode 100644 index 0000000..eac8619 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget3_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget4_thumbs.png b/modules/event_news/thumbs/event_news_widget4_thumbs.png new file mode 100644 index 0000000..b69abd9 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget4_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget5_thumbs.png b/modules/event_news/thumbs/event_news_widget5_thumbs.png new file mode 100644 index 0000000..cf6eb30 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget5_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget6_thumbs.png b/modules/event_news/thumbs/event_news_widget6_thumbs.png new file mode 100644 index 0000000..9fc7c23 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget6_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget7_thumbs.png b/modules/event_news/thumbs/event_news_widget7_thumbs.png new file mode 100644 index 0000000..0745dc6 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget7_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget8_thumbs.png b/modules/event_news/thumbs/event_news_widget8_thumbs.png new file mode 100644 index 0000000..7cfddf7 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget8_thumbs.png differ diff --git a/modules/event_news/thumbs/event_news_widget9_thumbs.png b/modules/event_news/thumbs/event_news_widget9_thumbs.png new file mode 100644 index 0000000..b0a2bb4 Binary files /dev/null and b/modules/event_news/thumbs/event_news_widget9_thumbs.png differ diff --git a/temp_file/Gemfile b/temp_file/Gemfile new file mode 100644 index 0000000..1e1bb1b --- /dev/null +++ b/temp_file/Gemfile @@ -0,0 +1,105 @@ +source 'https://rubygems.org' +#update all site!!!!!!!! +#social gems +gem "omniauth-google-oauth2" + +#rails gem +gem 'rake','~> 12.3.3' +gem 'sassc-rails', '~>1.3.0' +gem 'rails', '~> 4.1.16' +gem 'sanitize', '~> 4.6.6' +gem 'faraday', '~>0.15.4' +#assets and templates +#gem 'sass-rails', '~> 4.0.2' +gem 'uglifier', '>= 1.3.0' +gem 'coffee-rails', '~> 4.0.0' +gem 'jquery-rails' +gem 'jquery-ui-rails', "5.0.0" +gem 'turbolinks' +gem 'normalize-rails', '~> 3.0.1' +#password +gem 'bcrypt-ruby', '~> 3.1.5' + +#json +gem 'jbuilder', '~> 2.0' +gem 'sdoc', '~> 0.4.0', group: :doc +gem 'spring', '~> 1.7.2', group: :development +gem 'active_model_serializers' + +#parser +gem 'nokogiri', '~> 1.7.0.1' + +#store api +gem 'httparty' + +#database +# gem 'mongoid', github: "mongoid/mongoid" +gem 'mongoid', '~> 4.0.2' + + +# sockets +# gem "websocket-rails" + +#file uploading and carrierwave +gem "mini_magick", "3.5.0" +gem 'carrierwave' +gem 'carrierwave-mongoid','~> 0.10.0', :require => 'carrierwave/mongoid' +gem 'zip-zip' +gem 'kaminari', '~> 1.0.1' +gem 'kaminari-mongoid', '~> 0.1.0' +gem 'impressionist', '~> 1.5.2' +gem 'chartkick', '~> 2.3.5' +gem 'usagewatch_ext' +gem 'ckeditor', '~> 4.2.4' +gem 'unicorn', '~> 5.4.0' +gem 'zhconv' +gem 'time_difference' +gem 'execjs' +gem 'therubyracer' + +#excel +gem 'axlsx_rails' +gem 'spreadsheet' +gem 'rubyXL' + +#form helpers +gem 'dynamic_form' + +#built in modules +eval(File.read(File.dirname(__FILE__) + '/built_in_extensions.rb')) +#modules installed from the store +eval(File.read(File.dirname(__FILE__) + '/downloaded_extensions.rb')) +if File.exists?(File.dirname(__FILE__) + '/extra_gems.rb') + eval(File.read(File.dirname(__FILE__) + '/extra_gems.rb')) +end + +#development related gems +group :development do + gem 'better_errors' + # gem 'guard-bundler' + # gem 'guard-rails' + gem 'rails_layout' + gem 'rb-fchange', :require=>false + gem 'rb-fsevent', :require=>false + gem 'rb-inotify', '~> 0.9.10', :require=>false + gem 'byebug', '~> 9.0.6' + gem "binding_of_caller" +end + +#testing gems +group :test do + gem "minitest", '~>5.11.3' + gem 'minitest-spec-rails' +end + +#ask +gem 'rucaptcha',git: 'http://gitlab.tp.rulingcom.com/chiu/rucaptcha.git' +gem 'repost',git: 'http://gitlab.tp.rulingcom.com/chiu/repost-master.git' +gem 'payment_settup',git: 'http://gitlab.tp.rulingcom.com/chiu/payment_settup.git' +#caching observers +# gem 'mongoid-observers' + +#desktop +# gem 'angularjs-rails', '~> 1.2.20' +# gem 'angular-ui-bootstrap-rails', '~> 0.11.0' +# gem 'jquery_mousewheel_rails', '~> 3.1.11.3' diff --git a/temp_file/app/controllers/admin/playground_controller.rb b/temp_file/app/controllers/admin/playground_controller.rb new file mode 100644 index 0000000..665e82e --- /dev/null +++ b/temp_file/app/controllers/admin/playground_controller.rb @@ -0,0 +1,184 @@ +require "open3" +class Admin::PlaygroundController < OrbitAdminController + before_filter :check_for_testers, :only => "index" + layout "structure" + include Admin::PlaygroundHelper + before_action :clean_multithread_model, :only => :command + + def index + modules = ["announcement", "faq", "ad_banner", "archive", "gallery", "web_resource"] + @default_modules = modules.collect do |mod| + ma = ModuleApp.where(:key => mod).first + [ma.title,mod] + end + end + + def clean_multithread_model + mul = Multithread.where(key: 'playground').first + mul.destroy if !mul.nil? + end + + def generatefakedata + ma = ModuleApp.where(:key => params[:module]).first rescue nil + if !ma.nil? + case ma.key + when "announcement" + make_announcement_fake_data(ma, params[:number].to_i) + when "faq" + make_faq_fake_data(ma, params[:number].to_i) + when "ad_banner" + make_ad_banner_fake_data(ma, params[:number].to_i) + when "archive" + make_archive_fake_data(ma, params[:number].to_i) + when "gallery" + make_gallery_fake_data(ma, params[:number].to_i) + when "web_resource" + make_web_resource_fake_data(ma, params[:number].to_i) + end + end + render :json => {"success" => true}.to_json + end + + def deletefakedata + ma = params[:module] + fd = FakeData.where(:module => ma).first rescue nil + if !fd.nil? + case ma + when "announcement" + delete_announcement_fake_data(ma) + when "faq" + delete_faq_fake_data(ma) + when "ad_banner" + delete_ad_banner_fake_data(ma) + when "archive" + delete_archive_fake_data(ma) + when "gallery" + delete_gallery_fake_data(ma) + when "web_resource" + delete_web_resource_fake_data(ma) + end + else + render :json => {"success" => false}.to_json and return + end + render :json => {"success" => true}.to_json + end + + def command + response = {} + Multithread.create(key: 'playground',status: {output: [],error: false,alive:true}) + case params[:command] + when "clean" + clean_assets + response["success"] = true + when "precompile" + precompile + response["success"] = true + when "bundle" + bundle_update + response["success"] = true + when "restart_server" + restart_server + response["success"] = true + when "restart_unicorn" + restart_unicorn(Rails.env) + response["success"] = true + when "switch_to_production" + restart_unicorn("production") + response["success"] = true + when "switch_to_development" + restart_unicorn("development") + response["success"] = true + else + exec_other_command(params[:command]) + response["success"] = true + end + + render :json => response.to_json + end + + def console_output + if params[:type] == "restart" + render :json => {"success" => true}.to_json + file = File.join(Rails.root,"tmp","restart_unicorn.sh") + File.delete(file) if File.exists?(file) + else + mul = Multithread.where(key: 'playground').first + if !mul.nil? + render :json => {"alive" => mul.status['alive'], "response" => mul.status['output'][params[:count].to_i..-1], "error" => mul.status['error']}.to_json + if !mul.status['alive'] + mul.status['output'] = [] + mul.status['error'] = false + mul.save + end + else + render :json => {"alive" => true, "response" => "finish", "error" => false}.to_json + end + end + end + + private + + def precompile + cmd = "RAILS_ENV=production bundle exec rake assets:precompile" + exec_other_command(cmd) + end + + def exec_other_command(command) + mul = Multithread.where(key: 'playground').first + Thread.new do + begin + Bundler.with_clean_env do + IO.popen(command,:err=>[:child, :out]) do |stdout| + stdout.each do |line| + l = line.chomp + mul.status['output'] << l + if l == "rake aborted!" + mul.status['error'] = true + end + mul.save + end + end + mul.status['alive'] = false + mul.save + if command == 'bundle update' + system('sleep 2') + Bundler.with_clean_env{system("kill -s USR2 `cat tmp/pids/unicorn.pid`")} + end + end + rescue => e + mul.status['alive'] = false + mul.status['output'] << e.inspect + mul.status['error'] = true + mul.save + end + end + end + + def bundle_update + cmd = "bundle update" + exec_other_command(cmd) + end + + def restart_server + cmd ="kill -s USR2 `cat tmp/pids/unicorn.pid`" + exec_other_command(cmd) + end + + def clean_assets + cmd = "rm -r public/assets" + exec_other_command(cmd) + end + + def restart_unicorn(mode) + mode = Rails.env if mode.nil? + unicorn_rails = %x[which unicorn_rails].sub("\n",'') + content = "kill -s TERM `cat tmp/pids/unicorn.pid` && unset UNICORN_FD && sleep 1 && bundle exec #{unicorn_rails} -c config/unicorn.rb -D -E #{mode} | at now" + Thread.new do + Bundler.with_clean_env{system(content)} + end + end + + def check_for_testers + render_401 if !current_user.beta_tester && current_user.user_name != "rulingcom" + end +end \ No newline at end of file diff --git a/temp_file/app/controllers/admin/sites_controller.rb b/temp_file/app/controllers/admin/sites_controller.rb new file mode 100644 index 0000000..9259560 --- /dev/null +++ b/temp_file/app/controllers/admin/sites_controller.rb @@ -0,0 +1,265 @@ +class Admin::SitesController < OrbitAdminController + before_filter :get_site + before_filter :set_git_branch, :only=>[:check_updates, :update_orbit] + before_action :create_page_set + def create_page_set + @site = @current_site.nil? ? Site.first : @current_site + if( @site.page_sets.count==0 rescue false) + @site.page_sets.create() + elsif @site.page_sets.count>1 + @site.page_sets.each_with_index do |i,v| + if i!=0 + v.delete + end + end + end + end + layout "structure" + def send_email + params_to_send = {'store_token' => current_site.store_token} + uri = URI.parse(OrbitStore::URL) + http = Net::HTTP.new(uri.host,uri.port) + request = Net::HTTP::Get.new("/site/send_email") + request.body = params_to_send.to_query + http.open_timeout = 1 #set read_timeout to 1 second to avoid web die caused by no response + http.ssl_timeout = 1 + begin + response = http.request(request) + rescue + response = ActionDispatch::Response.new + response.body = {'success'=>true}.to_json + end + data = JSON.parse(response.body) + %x(kill -s USR2 `cat tmp/pids/unicorn.pid`) + sleep 5 + end + def index + @first_run = dashboard_is_first_run? + @registered = !@site.store_token.nil? + @store_permissions = check_store_permissions + if @store_permissions["error"] == "SITE_NOT_REGISTERED" + if @registered + @registered = false + @site.store_token = nil + @site.save + end + end + if @registered + network = ONetwork.new(OrbitStore::URL,"get") + response = network.request("/xhr/ticket/types",{"store_token" => @site.store_token}) + data = JSON.parse(response.body) rescue {} + @types = [] + locale = I18n.locale.to_s + if data["success"] == true + data["ticket_types"].each do |tt| + @types << [tt["title_translations"][locale],tt["id"]] + end + end + send_email if !@store_permissions["permission_granted"] rescue nil #Resend confirmation email if not confirmed + end + user_name = current_user.user_name rescue '' + network = ONetwork.new(OrbitStore::URL,"post") + response = network.request("/xhr/site/re_register_url",{"store_token" => current_site.store_token, 'site_domain' => request.host_with_port,'user' => user_name}) + @data = JSON.parse(response.body) rescue {} + end + + + def mail_setting + end + + def site_info + @pages = Page.where(:module=>"page_content") + end + + def responsive_setting + @module = ModuleApp.find_by_key("announcement") + end + + def search_engine + end + + def sitemap + end + + def change_design + @site.template = params[:design_key] + @site.save + restart_server + end + + def system_info + @disk_free = `df -h /`.gsub("\n","
").html_safe + @nginx_version = %x[/usr/sbin/nginx -v 2>&1].gsub("\n","
").html_safe + @mongo_version = `mongod --version`.split("\n")[0].html_safe + @linux_version = `lsb_release -d`.split(":")[1].html_safe rescue "Not Applicable" + + @user_actions = UserAction.all.desc(:created_at).page(params[:page]).per(10) + + @mail_crons = Email.can_deliver.desc(:created_at) + + @mail_cron_logs = EmailLog.desc(:created_at).page(params[:mail_log_page]).per(10) + + respond_to do |format| + format.html + format.js + end + end + + def delete_mail_log + if params[:ids] + EmailLog.any_in(:_id => params[:ids]).destroy + end + render :nothing => true + end + + def preference + end + + def update_orbit + end + + def update + @site.update_attributes(site_params) + + if params[:site][:enable_language_detection].eql?("0") + Site.update_all({:enable_language_detection => false}) + elsif params[:site][:enable_language_detection].eql?("1") + Site.update_all({:default_locale => nil}) + end + if !@site.in_use_locales.include?I18n.locale + I18n.locale = @site.in_use_locales.first + redirect_to admin_site_preference_path(current_site) + else + redirect_to :back + end + %x(kill -s USR2 `cat tmp/pids/unicorn.pid`) + sleep 5 + end + + def update_manager + @store_permissions = check_store_permissions + end + + def get_update_history + update_log = %x{git log --pretty=format:"%H','%ad','%s" --date=short}.split("\n") + emergency_log = %x{git reflog --pretty=format:"%H','%ad','%s" --date=short}.split("\n") + @update_log = update_log.collect do |v| + if v.include? 'complete_update_' + tmp = emergency_log.select{|v1| v1.exclude?('complete_update_') && v1.include?(v.split(/complete_update_/)[-1])}[0] rescue [] + [v,tmp] + else + v + end + end.flatten.map{|log| log.gsub("'","").split(",")}.to_json + render :json => @update_log + end + + def check_updates + %x(git fetch origin) + @new_updates = %x(git log #{@branch}..origin/#{@branch} --pretty=format:"%ad','%s" --date=short).split("\n").map{|log| log.gsub("'","").split(",")}.to_json + render :json => @new_updates + end + def git_reset(commit,type) + mul = Multithread.where(key: 'update_manager').first + mul = Multithread.create(key: 'update_manager') if mul.nil? + mul.update_attributes(status: 'waiting') + Thread.new do + ubuntu_version = %x[lsb_release -a | grep Release].scan(/\d.*\d/)[0] + git = 'git' + if Float(ubuntu_version) <= 14.04 && Float(%x[git --version].scan(/\d.\d/)[0]) < 1.9 + if %x[uname -m].scan('64').count !=0 + cmd0 = system("wget https://ruling.digital/uploads/asset/git_1.9.1-1_amd64.deb && dpkg -x git_1.9.1-1_amd64.deb ./git_1.9.1") + else + cmd0 = system("wget https://ruling.digital/uploads/asset/git_1.9.1-1_i386.deb && dpkg -x git_1.9.1-1_i386.deb ./git_1.9.1") + end + git = 'git_1.9.1/usr/bin/git' + end + git_add_except_public = Dir['*'].select{|v| v!= 'public' && v!= 'log' && v != 'dump' && v != 'tmp'}.collect do |v| + "#{git} add -f --all --ignore-errors '#{v}'" + end.join(' ; ') + git_add_custom = (Dir['*'].select{|v| v !='app' && v != 'lib' && v != 'config' && v != 'public' && v!= 'log' && v != 'dump' && v != 'tmp'} + ['app/templates','config/mongoid.yml','config/extra_lang.txt']).collect do |v| + "#{git} add -f --all --ignore-errors '#{v}'" + end.join(' ; ') + git_restore = "#{git} checkout ." + time_now = Time.now.strftime('%Y_%m_%d_%H_%M') + if %x[#{git} config user.name].empty? + %x[#{git} config --global user.name "rulingcom"] + end + if %x[#{git} config user.email].empty? + %x[#{git} config --global user.email "orbit@rulingcom.com"] + end + Bundler.with_clean_env{system("#{git_add_except_public} ; #{git} commit -m auto_backup_before_#{type}_#{time_now} --allow-empty && #{git} reset #{commit} --mixed ; #{git_add_custom} ; #{git_restore} ; #{git_add_except_public} ; #{git} commit -m complete_#{type}_#{time_now} --allow-empty")} + mul.update_attributes(status: 'finish') + end + end + def update_orbit + store_permissions = check_store_permissions + if params['type'] == 'update' + if store_permissions["permission_granted"] + git_reset('origin','update') + render :text => 'waiting' + else + render :json => store_permissions.to_json + end + elsif params['type'] == 'restore' + git_reset(params['id'],'restore') + render :text => 'waiting' + elsif params['type'] == 'get_result' + render :text => Multithread.where(key: 'update_manager').first.status rescue 'running' + end + end + + def bundle_install + Bundler.with_clean_env { system("cd #{Rails.root} && bundle update") } + %x(kill -s USR2 `cat tmp/pids/unicorn.pid`) + sleep 2 + render :nothing => true + end + + def restart_server + mode = Rails.env + unicorn_rails = %x[which unicorn_rails].sub("\n",'') + render :nothing => true + Bundler.with_clean_env{system("kill -s TERM `cat tmp/pids/unicorn.pid` && unset UNICORN_FD && sleep 1 && bundle exec #{unicorn_rails} -c config/unicorn.rb -D -E #{mode}")} + end + + private + def get_site + @site = @current_site.nil? ? Site.first : @current_site + end + + def dashboard_is_first_run? + !current_user.is_tour_completed?("tickets") + end + + def site_params + if params[:site][:default_bar_color] + params[:site][:mobile_bar_color] = [] + end + # if params[:site][:enable_language_detection] + # Site.update_all({:default_locale => nil}) + # end + + unless params[:site][:in_use_locales].nil? + in_user_locales = [] + I18n.available_locales.each do |locale| + in_user_locales << locale if params[:site][:in_use_locales][locale].eql?("1") + end + params[:site][:in_use_locales] = in_user_locales + end + + if params[:site][:phone_number].nil? + params[:site][:phone_number] = [] + # else + # params[:site][:phone_number] = params[:site][:phone_number] + end + params[:site][:sign_up_roles] = [] if !params[:site][:sign_up_roles].present? + params.require(:site).permit! + + end + + + def set_git_branch + @branch = %x(git rev-parse --abbrev-ref HEAD).gsub("\n","") + end +end diff --git a/temp_file/app/helpers/admin/playground_helper.rb b/temp_file/app/helpers/admin/playground_helper.rb new file mode 100644 index 0000000..1efcded --- /dev/null +++ b/temp_file/app/helpers/admin/playground_helper.rb @@ -0,0 +1,366 @@ +module Admin::PlaygroundHelper + + def make_announcement_fake_data(ma, total_count=5) + page = Page.Where(:module => ma.key).first rescue nil + if page.nil? + page = Page.new(:module => ma.key, :page_id => "announcements", :layout => "annc_index1", :name_translations => {"en" => "Announcement", "zh_tw" => "公告"}, :url => "/announcements", :enabled_for => ["en", "zh_tw"], :menu_enabled_for => ["en", "zh_tw"], :categories => ["all"], :tags => ["all"], :enabled_for_sitemap => ["en", "zh_tw"], :parent_page => Page.root) + page.save + end + if ma.categories.empty? + cat = Category.new + cat.title_translations = {"en" => "Announcement", "zh_tw" => "公告"} + cat.module_app = ma + cat.save + else + cat = ma.categories.first + end + if ma.tags.empty? + tag = Tag.new + tag.name_translations = {"en" => "Announcement", "zh_tw" => "公告"} + tag.module_app_ids << ma.id + tag.save + else + tag = ma.tags.first + end + fake_ids = [] + (1..total_count).each do |i| + bulletin = Bulletin.new(:title_translations => get_random_title, :subtitle_translations => get_random_subtitle, :text_translations => get_random_content, :create_user_id => current_user.id.to_s, :update_user_id => current_user.id.to_s, :deadline => get_fake_date, :approved => true, :image_description_translations => get_random_title) + bulletin.category = cat + bulletin.tags=tag + bulletin.is_top = get_random_status + bulletin.is_hot = get_random_status + bulletin.remote_image_url = get_fake_image_url(ma.key) + bulletin.save + fake_ids << bulletin.id + (1..rand(1..5)).each do |x| + bf = BulletinFile.new(:title_translations => get_random_title, :description_translations => get_random_title) + bf.remote_file_url = get_fake_file_url(ma.key) + bf.bulletin = bulletin + bf.save + end + (1..rand(1..5)).each do |x| + bl = BulletinLink.new(:title_translations => get_random_title, :url => get_fake_link) + bl.bulletin = bulletin + bl.save + end + end + commit_fake_data(ma, fake_ids) + end + + def delete_announcement_fake_data(ma) + fd = FakeData.where(:module => ma).first rescue nil + bulletins = Bulletin.where(:id.in => fd.ids) + bulletins.destroy_all + fd.destroy + end + + def make_ad_banner_fake_data(ma, total_count=5) + if ma.categories.empty? + cat = Category.new + cat.title_translations = {"en" => "Home Banners", "zh_tw" => "家庭橫幅"} + cat.module_app = ma + cat.save + else + cat = ma.categories.first + end + fake_ids = [] + fds = FakeData.where(:module => "ad_banner").first.ids.count rescue 0 + (1..total_count).each do |i| + banner = Banner.new(:title => "Home banner #{i + fds}", :ad_fx => "fade", :height => 300, :width => 800, :timeout => 5, :base_image => 1, :speed => 200) + banner.category = cat + banner.save + fake_ids << banner.id + (1..rand(2..4)).each do |x| + image = AdImage.new(:title_translations => get_random_title, :context_translations => get_random_title, :out_link => get_fake_link, :deadline => get_fake_date, :sort_number => x, :link_open => AdImage::LINK_OPEN_TYPES.sample) + image.remote_file_url = get_fake_image_url(ma.key) + image.banner = banner + image.save + end + end + commit_fake_data(ma, fake_ids) + end + + def delete_ad_banner_fake_data(ma) + fd = FakeData.where(:module => ma).first rescue nil + banners = Banner.where(:id.in => fd.ids) + banners.destroy_all + fd.destroy + end + + def make_faq_fake_data(ma, total_count=5) + page = Page.Where(:module => ma.key).first rescue nil + if page.nil? + page = Page.new(:module => ma.key, :page_id => "faqs", :layout => "faq_index1", :name_translations => {"en" => "FAQs", "zh_tw" => "FAQs"}, :url => "/faqs", :enabled_for => ["en", "zh_tw"], :menu_enabled_for => ["en", "zh_tw"], :categories => ["all"], :tags => ["all"], :enabled_for_sitemap => ["en", "zh_tw"], :parent_page => Page.root) + page.save + end + if ma.categories.empty? + cat = Category.new + cat.title_translations = {"en" => "FAQ", "zh_tw" => "FAQ"} + cat.module_app = ma + cat.save + else + cat = ma.categories.first + end + if ma.tags.empty? + tag = Tag.new + tag.name_translations = {"en" => "FAQ", "zh_tw" => "FAQ"} + tag.module_app_ids << ma.id + tag.save + else + tag = ma.tags.first + end + fake_ids = [] + (1..total_count).each do |i| + qa = Qa.new(:title_translations => get_random_title, :answer_translations => get_random_subtitle, :create_user_id => current_user.id.to_s, :update_user_id => current_user.id.to_s, :is_hot => get_random_status, :is_top => get_random_status) + qa.category = cat + qa.tags=tag + qa.save + fake_ids << qa.id + (1..rand(1..5)).each do |x| + qf = QaFile.new(:title_translations => get_random_title, :description_translations => get_random_title) + qf.remote_file_url = get_fake_file_url(ma.key) + qf.qa = qa + qf.save + end + (1..rand(1..5)).each do |x| + ql = QaLink.new(:title_translations => get_random_title, :url => get_fake_link) + ql.qa = qa + ql.save + end + end + commit_fake_data(ma, fake_ids) + end + + def delete_faq_fake_data(ma) + fd = FakeData.where(:module => ma).first rescue nil + faqs = Qa.where(:id.in => fd.ids) + faqs.destroy_all + fd.destroy + end + + def make_archive_fake_data(ma, total_count=5) + page = Page.Where(:module => ma.key).first rescue nil + if page.nil? + page = Page.new(:module => ma.key, :page_id => "archive", :layout => "archive_index1", :name_translations => {"en" => "Archive", "zh_tw" => "檔案"}, :url => "/archive", :enabled_for => ["en", "zh_tw"], :menu_enabled_for => ["en", "zh_tw"], :categories => ["all"], :tags => ["all"], :enabled_for_sitemap => ["en", "zh_tw"], :parent_page => Page.root) + page.save + end + if ma.categories.empty? + cat = Category.new + cat.title_translations = {"en" => "Archive", "zh_tw" => "檔案"} + cat.module_app = ma + cat.save + else + cat = ma.categories.first + end + if ma.tags.empty? + tag = Tag.new + tag.name_translations = {"en" => "Archive", "zh_tw" => "檔案"} + tag.module_app_ids << ma.id + tag.save + else + tag = ma.tags.first + end + fake_ids = [] + (1..total_count).each do |i| + archive = ArchiveFile.new(:title_translations => get_random_title, :create_user_id => current_user.id.to_s, :update_user_id => current_user.id.to_s, :deadline => get_fake_date, :is_top => get_random_status, :is_hot => get_random_status) + archive.category = cat + archive.tags=tag + archive.save + fake_ids << archive.id + (1..rand(1..5)).each do |x| + afm = ArchiveFileMultiple.new(:file_title_translations => get_random_title, :sort_number => x) + afm.remote_file_url = get_fake_file_url(ma.key) + afm.archive_file = archive + afm.save + end + end + commit_fake_data(ma, fake_ids) + end + + def delete_archive_fake_data(ma) + fd = FakeData.where(:module => ma).first rescue nil + archives = ArchiveFile.where(:id.in => fd.ids) + archives.destroy_all + fd.destroy + end + + def make_gallery_fake_data(ma, total_count=5) + page = Page.Where(:module => ma.key).first rescue nil + if page.nil? + page = Page.new(:module => ma.key, :page_id => "gallery", :layout => "gallery_index1", :name_translations => {"en" => "Gallery", "zh_tw" => "相簿"}, :url => "/gallery", :enabled_for => ["en", "zh_tw"], :menu_enabled_for => ["en", "zh_tw"], :categories => ["all"], :tags => ["all"], :enabled_for_sitemap => ["en", "zh_tw"], :parent_page => Page.root) + page.save + end + if ma.categories.empty? + cat = Category.new + cat.title_translations = {"en" => "Gallery", "zh_tw" => "相簿"} + cat.module_app = ma + cat.save + else + cat = ma.categories.first + end + if ma.tags.empty? + tag = Tag.new + tag.name_translations = {"en" => "Gallery", "zh_tw" => "相簿"} + tag.module_app_ids << ma.id + tag.save + else + tag = ma.tags.first + end + fake_ids = [] + (1..total_count).each do |i| + album = Album.new(:name_translations => get_random_title, :description_translations => get_random_subtitle) + album.tags=tag + album.category = cat + album.save + fake_ids << album.id + (1..rand(5..10)).each do |x| + image = AlbumImage.new(:title => get_random_title["zh_tw"], :description_translations => get_random_title, :order => x) + image.remote_file_url = get_fake_image_url(ma.key) + image.album = album + image.save + end + end + commit_fake_data(ma, fake_ids) + end + + def delete_gallery_fake_data(ma) + fd = FakeData.where(:module => ma).first rescue nil + albums = Album.where(:id.in => fd.ids) + albums.destroy_all + fd.destroy + end + + def make_web_resource_fake_data(ma, total_count=5) + page = Page.Where(:module => ma.key).first rescue nil + if page.nil? + page = Page.new(:module => ma.key, :page_id => "links", :layout => "web_res_index1", :name_translations => {"en" => "Links", "zh_tw" => "連結"}, :url => "/links", :enabled_for => ["en", "zh_tw"], :menu_enabled_for => ["en", "zh_tw"], :categories => ["all"], :tags => ["all"], :enabled_for_sitemap => ["en", "zh_tw"], :parent_page => Page.root) + page.save + end + if ma.categories.empty? + cat = Category.new + cat.title_translations = {"en" => "Links", "zh_tw" => "連結"} + cat.module_app = ma + cat.save + else + cat = ma.categories.first + end + if ma.tags.empty? + tag = Tag.new + tag.name_translations = {"en" => "Links", "zh_tw" => "連結"} + tag.module_app_ids << ma.id + tag.save + else + tag = ma.tags.first + end + fake_ids = [] + (1..total_count).each do |i| + link = WebLink.new(:title_translations => get_random_title, :context_translations => get_random_subtitle, :url_translations => {"en" => get_fake_link, "zh_tw" => get_fake_link}, :create_user_id => current_user.id.to_s, :update_user_id => current_user.id.to_s, :link_open => WebLink::LINK_OPEN_TYPES.sample, :is_top => get_random_status, :is_hot => get_random_status) + link.category = cat + link.tags=tag + link.save + fake_ids << link.id + end + commit_fake_data(ma, fake_ids) + end + + def delete_web_resource_fake_data(ma) + fd = FakeData.where(:module => ma).first rescue nil + links = WebLink.where(:id.in => fd.ids) + links.destroy_all + fd.destroy + end + + def get_fake_date(no=100) + Time.now + rand(1..no).days + end + + def get_fake_link + ["http://www.google.com", "http://www.rulingcom.com", "http://www.yahoo.com", "http://www.9gag.com", "http://www.youtube.com", "http://www.linkedin.com","http://www.imdb.com", "http://www.github.com", "http://www.google.co.in", "https://en.wikipedia.org/wiki/Wikipedia"].sample + end + + def commit_fake_data(ma, fake_ids) + fd = FakeData.where(:module => ma.key).first rescue nil + if fd.nil? + FakeData.create(:module => ma.key, :ids => fake_ids) + else + fd.ids = fd.ids.concat(fake_ids) + fd.save + end + end + + def get_fake_file_url(key) + OrbitStore::URL + "/fake_data/#{key}/files/" + rand(1..5).to_s + ".txt" + end + + def get_fake_image_url(key) + OrbitStore::URL + "/fake_data/#{key}/images/" + rand(1..15).to_s + ".jpg" + end + + def get_random_status + [true,false,true,true,false,false,false,false,false,false,false,true,false,true,false,true,false,false,true,false,true,false,true,false,false,false,false,false,true,false,true,false].sample + end + + def get_random_title + [ + { + "en" => "Lorem ipsum Quis deserunt culpa velit ea enim do labore ex.", + "zh_tw" => "廣州百萬招聘往往角色所有爆炸後面自從本站慢慢插件,一批研發雙手變成漸漸出去將在先生她們清楚寂寞降,功夫女性線路才能設置之家好處朋友警方放心連載有的創意教。" + }, + { + "en" => "Lorem ipsum Voluptate consectetur labore sed nisi Duis Duis in ut sit.", + "zh_tw" => "確實姓名走出被人相對壓縮生活關注培訓紡織有所裡面房,是有能源威脅他是文本上帝印刷年輕,深圳科技有限公司類別廣播我家機制我說加入接收執行時間,求購人物轉讓大聲相當運行中心,恢復據說資本人物專欄房屋記得感受謝謝市委用戶" + }, + { + "en" => "Lorem ipsum Ut adipisicing laboris tempor cillum eu tempor est minim ut deserunt elit sit.", + "zh_tw" => "對外購買創新發現跟著欣賞掌握第二天,最初結構投資體系招生髮表不滿請點擊手,那些結果警察一下回事可用其中避免贏得大學還是按照利潤。" + }, + { + "en" => "Chinese Lorem Ipsum includes the most common kanji chars and punctuation. Suggestions for improvements or alternatives are welcome.", + "zh_tw" => "速牧摘藤請能攜針紹掲式盤談。報厚勝月注揚件岡視申邊幅念七屬年。頼疑観小章的談集演選容善為真北上左。" + }, + { + "en" => "Lorem ipsum is a pseudo-Latin text used in web design, typography, layout, and printing in place of English to emphasise design elements over content.", + "zh_tw" => "側經意責家方家閉討店暖育田載社轉線宇。得君新術治溫抗添代話考振投員毆大北裁。" + }, + { + "en" => "Lorem ipsum Officia sed cillum aute magna consectetur nulla adipisicing magna.", + "zh_tw" => "英文業務體現首頁聽到禁止警察平衡誠信上次基金次數。" + }, + { + "en" => "Lorem ipsum Mollit officia sunt ea reprehenderit velit laborum.", + "zh_tw" => "解壓密碼效益價格女孩怪物高校互聯網交給商品人士儲存,優勢通過讓她都是親自一生現場大家動態,作用不同再度在此標題肯定優惠服。" + } + ].sample + end + + def get_random_subtitle + [ + { + "en" => "Lorem ipsum is a pseudo-Latin text used in web design, typography, layout, and printing in place of English to emphasise design elements over content. It's also called placeholder (or filler) text. It's a convenient tool for mock-ups.", + "zh_tw" => "財富整無必提引人懸身作渡健朝化紙事。人解食米生利娘法平終票織絶般改。文本行暮際對新左報事迫開件勝初測出人。速摘藤請能攜針紹式盤談。報厚勝月注揚件視申幅念七屬年。頼疑小章的談集演選容為真北左。" + }, + { + "en" => "While lorem ipsum's still resembles classical Latin, it actually has no meaning whatsoever. As Cicero's text doesn't contain the letters K, W, or Z, alien to latin, these, and others are often inserted randomly to mimic the typographic appearence of European languages, as are digraphs not to be found in the original.", + "zh_tw" => "目報貴代向能究介集分頃妻。休表化降最州別文東表住線。呼支保木前果告共芝暴禁玉姫五點稚。第色絡明域市造神草要督運流題。信下臨法職左通出官質給探。沖金普議雪受國女出般馬紙手災半塊。通別暮載典子郎將開展造能一。" + }, + { + "en" => "In a professional context it often happens that private or corporate clients corder a publication to be made and presented with the actual content still not being ready. Think of a news blog that's filled with content hourly on the day of going live. However, reviewers tend to be distracted by comprehensible content.", + "zh_tw" => "轉殺東入館特造賠感購予主市推製理承博。選被桶善外出神際抵法政。品誰非萬女話感合文昭。恐勢供村著雨木助階野食川園公大。連返一暮際平首寫一會未京美刃。珍者見藤石第返前鳥科宅様。直島載死談待思際考以響策依室參將機。演況民王手更愛五督銘索女。" + } + ].sample + end + + def get_random_content + [ + { + "en" => "Lorem ipsum In magna nisi aliquip enim ex consectetur. Lorem ipsum Id laboris veniam ullamco velit minim sit in aute commodo. Lorem ipsum Eiusmod nisi consectetur eu nostrud nisi et commodo laborum sint commodo. Lorem ipsum Irure aliquip laboris aliquip qui sint incididunt sunt nisi Ut pariatur. Lorem ipsum Sint culpa proident consequat sed eu proident ex ea dolor. Lorem ipsum Aliquip proident adipisicing fugiat fugiat consequat sed ex nulla. Lorem ipsum Labore culpa enim enim voluptate cillum velit labore esse voluptate. Lorem ipsum Aute est quis mollit consectetur reprehenderit. Lorem ipsum Pariatur et in Ut id laboris aute aliqua. Lorem ipsum Ut id non ad cillum non est ad sunt reprehenderit in nulla. Lorem ipsum Ea commodo cillum veniam Ut aute exercitation ullamco dolor aliqua. Lorem ipsum Quis anim ad officia esse ut magna. Lorem ipsum Irure aute reprehenderit officia esse qui ex laborum mollit Duis laboris.", + "zh_tw" => "對待證券首頁看法我和確認發布你看明顯之類答案透明多麼破,確保風險做法吸收不大,誘惑女子新手不論不可地上採購能力漫畫音樂營養河北笑,蒐集製造英國河南即可決策所說強化註冊還有廣場這麼這樣,好友音樂黃金有一定女,次數黑暗想法告知手續北京註冊。循環策略簡體中文股份塑料,加入時間經過會不會一家特色公告屬性協議多,公告穿著死亡說明角度體制交通路線期間太陽問題桌面依法,影視大學生道德虛擬業主自由不能,進去飛機本周越來越傳奇結構批發新人官員要有下,理念現像對比用戶名中國計算機目的,定位插件晚上加油年輕僅僅監督探索授權方式創業經營放棄。處理實現航空規定明天總,這一電源限制原因意思指數實驗表達互動代理體內較大早就代表,就不參數貢獻服務理論一方面計算進來貫徹規格面議不如監管證據,優秀監管試題回答容量,突破允許障礙考研你能也就是他們的我說空調也,拍攝男女增長其他官方方面發布結束模擬女子出了欄目我的心他,大幅備案無數貿易多種和平招聘,一時商標要在從事毫不手段經典可能會遭,高達旁邊演員代理適用於鑑定堅持管理。許多本次臨時發現小學前往第二章新型鏈接讓她這里聯賽鄭,相關讀者存儲博客零售最近多次付出造成請點擊也在房間帶,出去說是避免騎士還是注重不停網通相冊排行榜到處,尊重思路回到責任編輯每個人鬱,靈魂沒有甚至自己可能會說過出席化學新技術對手責任編輯可惜他說,家庭諾基亞沒事開通個性保密辛苦文檔選擇準備商城基本上他也休閒。" + }, + { + "en" => "Lorem ipsum Ad dolor in aliqua labore in dolor qui anim laborum. Lorem ipsum Et sed cillum anim nisi dolore. Lorem ipsum Enim sit dolor incididunt in tempor laborum nulla dolor nulla officia. Lorem ipsum Ut ea incididunt ad in esse eiusmod magna Excepteur sed esse. Lorem ipsum Cupidatat elit in ut dolore in mollit velit. Lorem ipsum Dolor enim aliqua consectetur veniam exercitation anim Duis occaecat aute in ex. Lorem ipsum Voluptate eiusmod sint pariatur quis velit aute enim fugiat. Lorem ipsum Officia dolore exercitation nisi qui minim anim id magna exercitation. Lorem ipsum Non in mollit veniam ut Excepteur officia. Lorem ipsum Ea in aliqua non ut commodo consequat commodo proident in anim. Lorem ipsum Culpa et Excepteur occaecat incididunt laborum pariatur ad ex reprehenderit. Lorem ipsum Cillum sed occaecat elit Excepteur Duis dolor exercitation commodo ut dolore. Lorem ipsum Sunt reprehenderit in dolore voluptate Excepteur ullamco pariatur sed dolore magna nisi. Lorem ipsum Mollit anim Ut elit aliqua labore laborum aliquip commodo nisi sint. Lorem ipsum Esse eu elit in nisi id sint nulla consectetur.", + "zh_tw" => "加入時間一樣轉讓能量人們導致要有互動初步同學手機是怎麼,無關比例穿著再說上來好像我愛充滿當,新聞支付不足增加發揮神經果然將。招商經濟發展不少最後條款準確不,接受之類觀點身影蘇州總部可見言論空中一會這個問題電子如果您,解放危機顯卡享受足夠味道快速分類回答生成聯。一款帶來監督獎勵也能台北提出開了前面檢查,監管液晶交易建設而言看過放下江湖對了航空,智慧現代化緊緊一邊哥,屏幕長大角色前面精神新華網,刷新物質滿意看看反饋情感放在購買男生簡,默認最重要男孩世界杯還可以獲取全市版主我,位於讓他菜單矛盾塑料讓我畢業生作用人大常委會清楚寂。它們排行榜一張優勢本身接著感情人間有時候排行他就,形式第二天加快查詢尷尬影視大全你有詳細勝利和你演出出,世界杯多多供應改革監督出台作出總結提高最快全體美元文明西,神經那天法院你會靈活備案味道減,總是處理器森林服務器便宜中央不得不福建,回應插件倒是我們告訴你多媒體政府江蘇遺憾開口哥哥,言論你想文學外貿將會母親辛苦部落分析例如高級對,有限責任公司回事核心只要它們以往哪些大幅提交優勢對外否則。全省讓我們享受騎士嘗試男生新華網據說用戶,數碼相機用戶名退出得到見面部門老公小區讓他大賽被人開了,職責溝通字幕普遍介紹運,每年有一些點這裡下載身子竟然篇文章全國新年多個是不是天津您。這段頭銜下降河北獲得防止獨立道理公主策劃部落方案其實,等等等待不錯客服以外提示商家面對新聞,虛擬排行榜可以說恢復此時加大優勢上漲第一。品牌天使本身電子放在勝,又有痛苦尤其是如有商品金額有限公司爭取森林舉報好評期,印刷說到一部分金錢酒店畢業生交友概念治理付出,患者研究真實污染大力外資西安一聲這麼多內置舉報投,進步上次所需治理上傳文件大小否則個人形成有限責任公司成果魔法。提前安排的是考研起來手指小心所以監控一看很難一,媽媽在線有限責任公司適應重視就好會員增加環境試驗青年謝謝四川,贏得客人生意賓館語文。一體情形接下來鈴聲玻璃數碼相機動物英,出了禮物值得書庫看起來開了,治理不喜歡互相妻子偉大頭銜滿意動力花,似乎立刻爭取魔獸作品把你頻道,價值工程種種鐵路模擬慢慢保持爆炸才是迅速同一進,接收相關配套分配案例以後方面,具體室內請大家路線法律責任會員你有多,傳真零售日韓人事避免教育活,協調同步實施身影一大等方面海外本。趕緊安排特色技巧它們如果你非法,位於是由稱為不肯不錯核心你是行情明,股東日期值得國產正文,水晶後面模樣出售好多,說到不足怎麼辦市場名單友情鏈接稿件事,成熟隨著轉移解決不在人類台灣還在,家族慢慢鐵通怎麼電器願意設置內容簡介點這裡自主創,發貼或是男子裝置舉行網通優勢不限交通沒事聯盟最。年齡寶寶你自己曝光儀器體會情況不可一台這次考生農業變化鼠標,情感就在這麼多結婚身上公里給我紡織轉讓,錄入流程形成真實過了預防是有其實科技設計,外資充分森林如有事業,股東欣賞污染開展法院山東還沒有英國英文投票。廣播本地下載均為部分還可以,理解一對平時為何精華並不地址老婆演,一對不能湖北爸爸讓她早就酒店權力歐,同一先進多個協調通過創造關心機構興奮有機會都,笑話文化請求稿件我這現實求助改革,標題令人限制批准是個聯賽理念竟然麻煩目前,導航街道上次最新是他次數需,先進性反而付款認識批准禮物像是郵政。水果合理不肯智能明天世,時間措施鍵盤大部分國家吸引東西藥品不大作為光臨所謂,有時發行將軍女性再說都沒裡面地上實際上股權語文而已運行平台結,郵編但我前面讓我們亞洲拿出必須人口商品全身突破退出作品當中計,具備出發反正您是公斤想要。" + } + ].sample + end + +end \ No newline at end of file diff --git a/temp_file/app/helpers/orbit_backend_helper.rb b/temp_file/app/helpers/orbit_backend_helper.rb new file mode 100644 index 0000000..fd938e6 --- /dev/null +++ b/temp_file/app/helpers/orbit_backend_helper.rb @@ -0,0 +1,237 @@ +require "uri" +require "net/http" +module OrbitBackendHelper + def self.included(base) + ActionView::Helpers::FormBuilder.send(:include,OrbitFormHelper) + end + + def group_impression_by_day(field,day_limit,start_day=Date.today,format = 'day') + limit_ele = Impression.desc(:id).where({ created_at: { "$lt" => start_day-(day_limit-2).days }}).first || Impression.first + key_op = [['year','$year'],['month', '$month'], ['day', '$dayOfMonth']] + key_op = key_op.take(1 + key_op.find_index { |key, op| format == key }) + project_date_fields = Hash[*key_op.collect { |key, op| [key, {op => "$#{field}"}] }.flatten] + group_id_fields = Hash[*key_op.collect { |key, op| [key, "$#{key}"] }.flatten] + pipeline = [ + {"$match"=> {"_id" => {"$gte" => (limit_ele['_id'] rescue '')}}}, + {"$project" => {field => 1}.merge(project_date_fields)}, + {"$group" => {"_id" => group_id_fields,"count" => {"$sum" => 1}}}, + {"$sort" => {"_id"=>-1}} + ] + tmp = Impression.collection.aggregate(pipeline) + if tmp.count < day_limit + tmp1 = tmp + tmp = (0...day_limit).collect do |i| + d = start_day - i.days + d_year = d.year + d_month = d.month + d_day = d.day + count = tmp1.select do |v| + n_date = v['_id'] + n_date['year']==d_year && n_date['month']==d_month && n_date['day']==d_day + end[0]['count'] rescue 0 + {'_id'=>{'year'=>d_year,'month'=>d_month,'day'=>d_day},'count'=>count} + end + puts ['tmp',tmp] + end + tmp + end + def thead(field,center=false,enable_sort=true) + sort = field.to_s.include?('.') ? field.to_s.split('.')[1] : field.to_s + active = params[:sort].eql? sort + order = active ? (["asc", "desc"]-[params[:order]]).first : "asc" + arrow = (order.eql? "desc") ? "" : "" + klass = field.eql?(:title) ? "span5" : "span2" + + th_data = (sort=="preview" || !enable_sort) ? t(field.to_sym) : "#{t(field.to_sym)} #{active ? arrow : ""}" + + "#{th_data}".html_safe + end + + + def add_attribute(partial, f, attribute) + new_object = f.object.send(attribute).build rescue nil + fields = f.fields_for(attribute, new_object, :child_index => "new_#{attribute}") do |f| + render :partial => partial, :object => new_object, :locals => {:f => f} + end + end + + def is_filter_active?(field, value) + params[:filters][field].include?(value.to_s) ? "active" : "" rescue "" + end + + + def select_category(f, module_app) + @user_authorized_categories = module_app.categories.enabled.authorized(current_user) if @user_authorized_categories.nil? + render :partial => '/admin/categories/select_form', :locals => {:f=> f, :module_app=>module_app, :categories=> @user_authorized_categories } + end + + def copy_to_all_language_button(language_tab, language_area) + render :partial => '/shared/copy_to_all_language_button', :locals => {:language_area => language_area, :language_tab => language_tab} + end + + def select_tags(f, module_app) + render :partial => '/admin/tags/tag_form', :locals => {:f=> f, :module_app=>module_app, :tags=>module_app.tags } + end + + def render_filter(fields, search_dom_id=nil, quick_new=false) + render :partial => "shared/filter", :locals =>{:fields => fields, :search_dom_id=>search_dom_id, :quick_new=>quick_new} + end + + def display_visitors(options={}) + Impression.where(options).count + end + + def display_visitors_today + if (defined? @result_of_thirty_day).nil? + display_visitors(created_at: {'$gte' => Time.now.beginning_of_day}) + else + @result_of_thirty_day[0]['count'] + end + end + + def display_visitors_this_week + if (defined? @result_of_thirty_day).nil? + display_visitors(created_at: {'$gte' => Time.now.beginning_of_week}) + else + @result_of_thirty_day[0..((Time.now-Time.now.beginning_of_week)/86400).floor].map{|v| v['count']}.reduce{|v,x| v+x} + end + end + + def display_visitors_this_month + if (defined? @result_of_thirty_day).nil? + visitors_this_month = Rails.cache.fetch("visitors_this_month", expires_in: 1.day) do + display_visitors(created_at: {'$gte' => Time.now.beginning_of_month}) + end + visitors_this_month + else + @result_of_thirty_day[0..((Time.now-Time.now.beginning_of_month)/86400).floor].map{|v| v['count']}.reduce{|v,x| v+x} + end + end + + def display_visitors_this_year + visitors_this_year = Rails.cache.fetch("visitors_this_year", expires_in: 1.day) do + display_visitors(created_at: {'$gte' => Time.now.beginning_of_year}) + end + visitors_this_year + end + + def get_month_traffic + #site = Site.first + #if site.month_traffic_cache.blank? or (site.month_traffic_cache['updated_at'] < (Time.now-1.day) rescue true) + #site.month_traffic_cache = {} + #site.month_traffic_cache['result'] = [] + @result_of_thirty_day = group_impression_by_day(:created_at,30) + trafic_result = @result_of_thirty_day.map do |v| + date = v['_id'].values + [Date.new(date[0],date[1],date[2]).to_time,v['count']] + end + #site.month_traffic_cache['result'] = trafic_result + #site.month_traffic_cache['updated_at'] = Time.now + #site.save + #end + + #[:name=> t(:visitors_count),:data=>site.month_traffic_cache['result']] + [:name=> t(:visitors_count),:data=>trafic_result] + end + + def can_edit_or_delete?(obj) + create_user = obj.create_user_id.to_s rescue nil + if @user_authenticated_categories.first == "all" + return true + elsif obj.class == Page && current_user.is_manager?(ModuleApp.where(:key=>'page_content').first) + return true + elsif @current_user_is_sub_manager && !create_user.nil? + create_user == current_user.id.to_s + else + @user_authenticated_categories.include?obj.category_id rescue (current_user.is_manager?(@module_app) rescue false) + end + end + + def user_authenticated_categories + @user_authenticated_categories + end + + def is_user_sub_manager? + @current_user_is_sub_manager + end + + def has_access? #@user_has_privileges comes from orbit_member_controller.. used just in members + @user_has_privileges + end + + def check_store_permissions #checks with the store if it has proper access and rights to access store + store_permission = {} + store_token = current_site.store_token rescue nil + if !store_token.nil? + params_to_send = {'store_token' => current_site.store_token} + uri = URI.parse(OrbitStore::URL) + http = Net::HTTP.new(uri.host,uri.port) + http.read_timeout = 25 #seconds + request = Net::HTTP::Get.new("/site/permissions") + request.body = params_to_send.to_query + http.open_timeout = 1 #set read_timeout to 1 second to avoid web die caused by no response + http.ssl_timeout = 1 + begin + response = http.request(request) + rescue + response = ActionDispatch::Response.new + response.body = {'success'=>true}.to_json + end + if response.nil? + data = {} + data["message"] = "Could not connect to the store." + data["error"] = "CONNECTION_REFUSED" + data["success"] = false + else + data = JSON.parse(response.body) rescue nil + end + if data.nil? + data = {} + data["message"] = "Could not connect to the store." + data["error"] = "JSON_ERROR" + data["success"] = false + end + if !data["success"] + case data["error"] + when "INVALID_SITE_TOKEN" + current_site.store_token = nil + current_site.save + end + store_permission["permission_granted"] = false + store_permission["error"] = data["error"] + store_permission["message"] = data["message"] + else + store_permission["permission_granted"] = true + end + else + store_permission["permission_granted"] = false + store_permission["error"] = "SITE_NOT_REGISTERED" + store_permission["message"] = "Site not registered." + end + store_permission + end + + def render_401 + render "errors/401" + end + + def render_403 + render "errors/403" + end + + def need_access_right + render_401 if !has_access? + end + + def get_referer_url + referer_path = Rails.application.routes.recognize_path(request.referer) + if referer_path[:controller]!="pages" or (referer_path[:controller]==params[:controller] and referer_path[:action]!="index") + referer_url = '/'+params[:controller] + else + referer_url = request.referer + end + referer_url + end + +end + diff --git a/temp_file/app/helpers/orbit_form_helper.rb b/temp_file/app/helpers/orbit_form_helper.rb new file mode 100644 index 0000000..bffe793 --- /dev/null +++ b/temp_file/app/helpers/orbit_form_helper.rb @@ -0,0 +1,150 @@ +module OrbitFormHelper + def self.included(base) + #ActionView::Helpers::FormBuilder.send(:include, Orbit::FormBuilder) + ActionView::Helpers::FormBuilder.send(:include,ActionView::Helpers::UrlHelper) + ActionView::Helpers::FormBuilder.send(:include,ActionView::Helpers::TagHelper) + ActionView::Helpers::FormBuilder.send(:include,ActionView::Context) + ActionView::Helpers::FormBuilder.send(:include,ActionView::Helpers::FormTagHelper) + end + + def datetime_picker(object_name, options = {}) + options[:icon_time] ||= 'icons-clock' + options[:icon_date] ||= 'icons-calendar' + options[:icon_clear] ||= 'icons-cross-3' + options[:input_class] ||= 'input-large' + options[:new_record] = true if options[:new_record].nil? + options = objectify_options(options) + options[:value] ||= options[:object].send(object_name) if options[:object] && options[:object][object_name] + options[:placeholder] ||= (options[:format].to_s.empty? ? nil : options[:format]) + case options[:picker_type] + when 'date' + content_tag :div, :id => options[:id], :class => options[:class] do + date_picker(object_name, options) + end + when 'time' + content_tag :div, :id => options[:id], :class => options[:class] do + time_picker(object_name, options) + end + when 'separated' + options[:label] ||= I18n.t('datetime_picker.separated.label') + content_tag :div, :id => options[:id], :class => "separated_picker #{options[:class]}" do + concat label_tag options[:label] unless options[:no_label] + concat hidden_field(object_name, :value => options[:value]) + concat separated_picker(object_name, options) + end + when 'simple' + content_tag :div, :id => options[:id], :class => options[:class] do + simple_picker(object_name, options) + end + else + content_tag :div, :id => options[:id], :class => options[:class] do + default_picker(object_name, options) + end + end + end + + def default_picker(object_name, options) + custom = {} + options[:format] = options[:format] || 'yyyy/MM/dd hh:mm' + options[:value] = format_value(options[:value], options[:format]) if options[:value] && !options[:new_record] + options[:value] = "" if options[:new_record] + custom[:picker_class] = 'default_picker' + custom[:label] = options[:label] || I18n.t('datetime_picker.default.label') + custom[:placeholder] = options[:placeholder] || I18n.t('datetime_picker.default.placeholder') + picker(object_name, options.merge(custom)) + end + + def picker(object_name, options) + content_tag :div, :class => "#{options[:picker_class]} input-append" do + concat label_tag options[:label] unless options[:no_label] + if object_name.nil? + if !options['id'].nil? + concat text_field_tag nil ,options[:value], :placeholder => options[:placeholder], :class => options[:input_class], 'data-format' => options[:format], :data => options[:data], :id => options['id'] + else + concat text_field_tag nil,options[:value], :placeholder => options[:placeholder], :class => options[:input_class], 'data-format' => options[:format], :data => options[:data] + end + else + if !options['id'].nil? + concat text_field object_name , :placeholder => options[:placeholder], :class => options[:input_class], 'data-format' => options[:format], :value => options[:value], :data => options[:data], :id => options['id'] + else + concat text_field object_name, :placeholder => options[:placeholder], :class => options[:input_class], 'data-format' => options[:format], :value => options[:value], :data => options[:data] + end + end + concat (content_tag :span, :class => 'add-on clearDate' do + content_tag :i, nil, :class => options[:icon_clear] + end) + concat (content_tag :span, :class => 'add-on iconbtn' do + content_tag :i, nil, 'data-time-icon' => options[:icon_time], 'data-date-icon' => options[:icon_date] + end) + end + end + + def format_value(value, format = 'yyyy-MM-dd hh:mm') + value.strftime(format.gsub('yyyy', '%Y').gsub('MM', '%m').gsub('dd', '%d').gsub('hh', '%H').gsub('mm', '%M')) rescue "" + end + + + def simple_picker(object_name, options) + onkeypress_for_input = 'return (event.charCode >= 48 && event.charCode <= 57) || event.keyCode == 8 || event.keyCode == 46 || (event.keyCode >= 37 && event.keyCode <= 40) || event.keyCode == 9' + onkeyup_for_input = 'this.value=(this.value.length <= 2 ? (parseInt(this.value) > 0 && parseInt(this.value) < 32 ? this.value : this.value.substring(0,this.value.length-1)) : this.value.substring(0,this.value.length-1))' + onkeyup_for_input2 = 'this.value=(this.value.length == 4 ? (parseInt(this.value) > 1900 && parseInt(this.value) < 3000 ? this.value : this.value.substring(0,this.value.length-1)) : (this.value.length > 4 ? this.value.substring(0,this.value.length-1) : this.value))' + html = "
+ + " + html = html + hidden_field(object_name, :value => options[:value] || "1901-01-01") + html = html + "
" + html.html_safe + end + + def date_picker(object_name, options) + custom = {} + custom[:format] = options[:format] || 'yyyy/MM' + custom[:value] = format_value(options[:value], custom[:format]) if options[:value] + custom[:picker_class] = 'date_picker' + custom[:label] = options[:label] || I18n.t('datetime_picker.date.label') + options[:placeholder] ||= I18n.t('datetime_picker.date.placeholder') + picker(object_name, options.merge(custom)) + end + + def time_picker(object_name, options) + custom = {} + custom[:format] = options[:format] || 'hh:mm' + custom[:value] = format_value(options[:value], custom[:format]) if options[:value] + custom[:picker_class] = 'time_picker' + custom[:label] = options[:label] || I18n.t('datetime_picker.time.label') + custom[:placeholder] = options[:placeholder] || I18n.t('datetime_picker.time.placeholder') + picker(object_name, options.merge(custom)) + end + + def separated_picker(object_name, options) + custom = {} + custom[:no_label] = true + custom[:separated] = true + date_picker(nil, options.merge(custom).merge({:format=>'yy/mm/dd','id'=>"_1_#{object_name}"})) + time_picker(nil, options.merge(custom).merge({:format=>'hh:mm','id'=>"_2_#{object_name}"})) + end + + + def single_picker(object_name, options) + content_tag :div, :id => options[:id], :class => options[:class] do + picker(object_name, options) + end + end + + def double_picker(object_name, options) + + end + + +end + +module Orbit::FormBuilder + # ActionPack's metaprogramming would have done this for us, if FormHelper#labeled_input + # had been defined at load. Instead we define it ourselves here. + #def datetime_picker(method, options = {}) + # @template.datetime_picker(@object_name, method, objectify_options(options)) + #end +end \ No newline at end of file diff --git a/temp_file/app/models/multithread.rb b/temp_file/app/models/multithread.rb new file mode 100644 index 0000000..25cefd9 --- /dev/null +++ b/temp_file/app/models/multithread.rb @@ -0,0 +1,5 @@ +class Multithread + include Mongoid::Document + field :key + field :status +end diff --git a/temp_file/app/models/page_set.rb b/temp_file/app/models/page_set.rb new file mode 100644 index 0000000..4b3de87 --- /dev/null +++ b/temp_file/app/models/page_set.rb @@ -0,0 +1,6 @@ +class PageSet + include Mongoid::Document + include Mongoid::Timestamps + belongs_to :site + field :auto_convert_flag, type: Boolean, :default => false +end \ No newline at end of file diff --git a/temp_file/app/models/site.rb b/temp_file/app/models/site.rb new file mode 100644 index 0000000..581f2d3 --- /dev/null +++ b/temp_file/app/models/site.rb @@ -0,0 +1,117 @@ +class Site + include Mongoid::Document + include Mongoid::Timestamps + include Slug + + DEBUG = false + has_many :page_sets, :autosave => true, :dependent => :destroy + accepts_nested_attributes_for :page_sets, :allow_destroy => true + field :title, as: :slug_title, type: String, localize: true + field :school, type: String + field :department, type: String + field :address, type: String + field :footer, localize: true + field :social_share, type: String + field :sub_menu, localize: true + field :site_type + field :site_map_link, type: String, :default => "/sitemap" + field :terms_of_use_link, type: String + field :google_analytics, type: String + field :in_use_locales, :type => Array + field :valid_locales, :type => Array + field :site_active, :type => Boolean + field :frontend_open, :type => Boolean, :default => true + field :backend_openness_on, :type => Boolean, :default => false + field :mobile_api_openness_on, :type => Boolean, :default => false + field :desktop_closed, :type => Boolean, :default => false + field :enable_language_detection, :type => Boolean, :default => false + field :enable_redirect_index, :type => Boolean, :default => true + field :enable_zh_cn, :type => Boolean, :default => true + field :enable_language_options, :type => Boolean, :default => true + field :default_locale, :default => "zh_tw" + field :mobile_on, :type => Boolean, :default => false + field :announcement_category, :type => Array, :default=>[] + field :mobile_bar_color, :type => Array, :default=>[] + field :phone_number, :type => Array,:default=>[] + field :title_always_on, :type => Boolean, :default => false + field :display_title_in_frontend, :type => Boolean, :default => true + field :sitemap_menu_in_header, :type => Boolean, :default => false + field :enable_terms_of_use, :type => Boolean, :default => false + field :search,:type => Hash + field :site_settings + field :template, type: String + field :store_token + field :enable_last_update, type: Boolean, :default => false + field :personal_plugins_sort, type: Array, :default => [] + field :sign_up_roles, type: Array, :default => [] + field :required_sign_up_attributes , :type => Hash , :default => {} + field :mobile_orbit_bar_title, localize: true + field :google_oauth_enabled, :type => Boolean, :default => false + field :google_client_id + field :google_client_secret + field :meta_tags + field :every_page_sharer, type: Array, :default => ["facebook","twitter","google","printer"] + + field :sync_enabled, type: Boolean, :default => false + field :sync_rake_task + + field :month_traffic_cache + field :home_link, :type => String, :default=>"/" + field :home_link_1, :type => String, :default=>"/" + field :site_title, :type => Hash, :default=>{:zh_tw=>"主頁",:en=>"home_page"} + field :site_title_1, :type => Hash, :default=>{:zh_tw=>"主頁",:en=>"home_page"} + field :is_hidden_orbit_bar , type: Boolean, :default => false + field :orbit_bar_background_color , type: String, :default => "" + field :orbit_bar_background_hover_color + field :orbit_bar_text_color , type: String, :default => "#ffffff" + field :orbit_bar_text_hover_color + field :orbit_bar_submenu_background_color , type: String, :default => "" + field :orbit_bar_submenu_text_color , type: String, :default => "#ffffff" + field :orbit_bar_animation_time , type: String, :default => "0.3s" + field :login_text , type: String, :default => "", localize: true + mount_uploader :default_image, ImageUploader + mount_uploader :site_logo, ImageUploader + mount_uploader :site_logo_1, ImageUploader + mount_uploader :favicon, ImageUploader + mount_uploader :mobile_icon, ImageUploader + after_initialize do |record| + if !record.new_record? + if record.is_hidden_orbit_bar.nil? + record.is_hidden_orbit_bar = false + record.save + end + if record.orbit_bar_background_color.nil? + record.orbit_bar_background_color = "" + record.save + end + if record.orbit_bar_text_color.nil? + record.orbit_bar_text_color = "" + record.save + end + if record.orbit_bar_submenu_background_color.nil? + record.orbit_bar_submenu_background_color = "" + record.save + end + if record.orbit_bar_submenu_text_color.nil? + record.orbit_bar_submenu_text_color = "" + record.save + end + if record.orbit_bar_animation_time.nil? + record.orbit_bar_animation_time = "0.3s" + record.save + end + end + if record.orbit_bar_background_color == '#000000' && record.orbit_bar_text_color == '#000000' + record.update(:orbit_bar_text_color => '#ffffff') + end + if record.orbit_bar_submenu_background_color == '#000000' && record.orbit_bar_submenu_text_color == '#000000' + record.update(:orbit_bar_submenu_text_color => '#ffffff') + end + end + def register_site(url,university,department,email,country) + api_key = STORE_CONFIG[:store_settings]["api_key"] + self.generate_site_token + store = Store.new(self.id.to_s,self.site_token,api_key) + store.post_client(self.id.to_s,self.site_token,self.title,url,university,department,email,country) + end +end diff --git a/temp_file/app/views/admin/sites/_notifications.html.erb b/temp_file/app/views/admin/sites/_notifications.html.erb new file mode 100644 index 0000000..998f717 --- /dev/null +++ b/temp_file/app/views/admin/sites/_notifications.html.erb @@ -0,0 +1,54 @@ + + + + +<% Array(@data['site_anncs']).compact.each_with_index do |v,i| %> +
+
+ <%= v['content'][I18n.locale.to_s].to_s.html_safe %> +
+
+<% end %> +
+ +

+ + + Messages from RulingCare +

+
+
+ + + <% Array(@data['site_anncs']).compact.each_with_index do |v,i| %> + + + + <% end %> + +
<%= v['title'][I18n.locale.to_s].to_s.html_safe %>
+
\ No newline at end of file diff --git a/temp_file/app/views/admin/sites/update_manager.erb b/temp_file/app/views/admin/sites/update_manager.erb new file mode 100644 index 0000000..d0a0eae --- /dev/null +++ b/temp_file/app/views/admin/sites/update_manager.erb @@ -0,0 +1,310 @@ + + +
+
+
+
+
+
+ + + <%= t("update_manager_.available_updates") %> + + <% if !@store_permissions["permission_granted"] %> + + + <% if @store_permissions["message"].size > 30 %> + "><%= @store_permissions["message"][0..17] + "..." %> + + <% else %> + <%= @store_permissions["message"] %> + <% end %> + + <% end %> +
+
+ + + + +
+
+
+
+ <% if @store_permissions["permission_granted"] %> + + <% else %> + Please register here. + <% end %> +
+
+
+
+
+ + + <%= t("update_manager_.update_status") %> + <% if !@store_permissions["permission_granted"] %> + + <% if @store_permissions["message"].size > 30 %> + "><%= @store_permissions["message"][0..17] + "..." %> + + <% else %> + <%= @store_permissions["message"] %> + <% end %> + + <% end %> +
+
+
+     <%= t("update_manager_.update_done") %> +
+
+     <%= t("update_manager_.update_faild") %> +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ + + <%= t("update_manager_.update_history") %> + +
+
+ + + + +
+
+
+
+
+
+ \ No newline at end of file diff --git a/test/bulletin_test.rb b/test/bulletin_test.rb new file mode 100644 index 0000000..10cd840 --- /dev/null +++ b/test/bulletin_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class BulletinTest < ActiveSupport::TestCase + test "truth" do + assert_kind_of Module, Bulletin + end +end diff --git a/test/controllers/admin/announcements_controller_test.rb b/test/controllers/admin/announcements_controller_test.rb new file mode 100644 index 0000000..1bacec2 --- /dev/null +++ b/test/controllers/admin/announcements_controller_test.rb @@ -0,0 +1,14 @@ +require 'test_helper' + +class Admin::AnnouncementsControllerTest < ActionController::TestCase + test "should get new" do + get :new + assert_response :success + end + + test "should get create" do + get :create + assert_response :success + end + +end diff --git a/test/dummy/README.rdoc b/test/dummy/README.rdoc new file mode 100644 index 0000000..dd4e97e --- /dev/null +++ b/test/dummy/README.rdoc @@ -0,0 +1,28 @@ +== README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... + + +Please feel free to use a different markup language if you do not plan to run +rake doc:app. diff --git a/test/dummy/Rakefile b/test/dummy/Rakefile new file mode 100644 index 0000000..ba6b733 --- /dev/null +++ b/test/dummy/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Rails.application.load_tasks diff --git a/test/dummy/app/assets/images/.keep b/test/dummy/app/assets/images/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/assets/javascripts/application.js b/test/dummy/app/assets/javascripts/application.js new file mode 100644 index 0000000..5bc2e1c --- /dev/null +++ b/test/dummy/app/assets/javascripts/application.js @@ -0,0 +1,13 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. +// +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require_tree . diff --git a/test/dummy/app/assets/stylesheets/application.css b/test/dummy/app/assets/stylesheets/application.css new file mode 100644 index 0000000..a443db3 --- /dev/null +++ b/test/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/test/dummy/app/controllers/application_controller.rb b/test/dummy/app/controllers/application_controller.rb new file mode 100644 index 0000000..d83690e --- /dev/null +++ b/test/dummy/app/controllers/application_controller.rb @@ -0,0 +1,5 @@ +class ApplicationController < ActionController::Base + # Prevent CSRF attacks by raising an exception. + # For APIs, you may want to use :null_session instead. + protect_from_forgery with: :exception +end diff --git a/test/dummy/app/controllers/concerns/.keep b/test/dummy/app/controllers/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/helpers/application_helper.rb b/test/dummy/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/test/dummy/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/test/dummy/app/mailers/.keep b/test/dummy/app/mailers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/models/.keep b/test/dummy/app/models/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/models/concerns/.keep b/test/dummy/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb new file mode 100644 index 0000000..593a778 --- /dev/null +++ b/test/dummy/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + Dummy + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> + <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + + + +<%= yield %> + + + diff --git a/test/dummy/bin/bundle b/test/dummy/bin/bundle new file mode 100644 index 0000000..66e9889 --- /dev/null +++ b/test/dummy/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/test/dummy/bin/rails b/test/dummy/bin/rails new file mode 100644 index 0000000..728cd85 --- /dev/null +++ b/test/dummy/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/test/dummy/bin/rake b/test/dummy/bin/rake new file mode 100644 index 0000000..1724048 --- /dev/null +++ b/test/dummy/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/test/dummy/config.ru b/test/dummy/config.ru new file mode 100644 index 0000000..5bc2a61 --- /dev/null +++ b/test/dummy/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Rails.application diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb new file mode 100644 index 0000000..091c8f5 --- /dev/null +++ b/test/dummy/config/application.rb @@ -0,0 +1,29 @@ +require File.expand_path('../boot', __FILE__) + +# Pick the frameworks you want: +# require "active_record/railtie" +require "action_controller/railtie" +require "action_mailer/railtie" +require "action_view/railtie" +require "sprockets/railtie" +require "rails/test_unit/railtie" + +Bundler.require(*Rails.groups) +require "bulletin" + +module Dummy + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # 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 + end +end + diff --git a/test/dummy/config/boot.rb b/test/dummy/config/boot.rb new file mode 100644 index 0000000..6266cfc --- /dev/null +++ b/test/dummy/config/boot.rb @@ -0,0 +1,5 @@ +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) diff --git a/test/dummy/config/environment.rb b/test/dummy/config/environment.rb new file mode 100644 index 0000000..ee8d90d --- /dev/null +++ b/test/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require File.expand_path('../application', __FILE__) + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb new file mode 100644 index 0000000..a384d95 --- /dev/null +++ b/test/dummy/config/environments/development.rb @@ -0,0 +1,34 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Adds additional error checking when serving assets at runtime. + # Checks for improperly declared sprockets dependencies. + # Raises helpful error messages. + config.assets.raise_runtime_errors = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb new file mode 100644 index 0000000..4f67ce3 --- /dev/null +++ b/test/dummy/config/environments/production.rb @@ -0,0 +1,80 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Enable Rack::Cache to put a simple HTTP cache in front of your application + # Add `rack-cache` to your Gemfile before enabling this. + # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. + # config.action_dispatch.rack_cache = true + + # Disable Rails's static asset server (Apache or nginx will already do this). + config.serve_static_assets = false + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # Generate digests for assets URLs. + config.assets.digest = true + + # Version of your assets, change this if you want to expire all your assets. + config.assets.version = '1.0' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Set to :debug to see everything in the log. + config.log_level = :info + + # Prepend all log lines with the following tags. + # config.log_tags = [ :subdomain, :uuid ] + + # Use a different logger for distributed setups. + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = "http://assets.example.com" + + # Precompile additional assets. + # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. + # config.assets.precompile += %w( search.js ) + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Disable automatic flushing of the log to improve performance. + # config.autoflush_log = false + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new +end diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb new file mode 100644 index 0000000..053f5b6 --- /dev/null +++ b/test/dummy/config/environments/test.rb @@ -0,0 +1,39 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure static asset server for tests with Cache-Control for performance. + config.serve_static_assets = true + config.static_cache_control = 'public, max-age=3600' + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/test/dummy/config/initializers/backtrace_silencers.rb b/test/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/test/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/test/dummy/config/initializers/cookies_serializer.rb b/test/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000..7a06a89 --- /dev/null +++ b/test/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.action_dispatch.cookies_serializer = :json \ No newline at end of file diff --git a/test/dummy/config/initializers/filter_parameter_logging.rb b/test/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..4a994e1 --- /dev/null +++ b/test/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/test/dummy/config/initializers/inflections.rb b/test/dummy/config/initializers/inflections.rb new file mode 100644 index 0000000..ac033bf --- /dev/null +++ b/test/dummy/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/test/dummy/config/initializers/mime_types.rb b/test/dummy/config/initializers/mime_types.rb new file mode 100644 index 0000000..72aca7e --- /dev/null +++ b/test/dummy/config/initializers/mime_types.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf +# Mime::Type.register_alias "text/html", :iphone diff --git a/test/dummy/config/initializers/session_store.rb b/test/dummy/config/initializers/session_store.rb new file mode 100644 index 0000000..e766b67 --- /dev/null +++ b/test/dummy/config/initializers/session_store.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.session_store :cookie_store, key: '_dummy_session' diff --git a/test/dummy/config/initializers/wrap_parameters.rb b/test/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..b81ea74 --- /dev/null +++ b/test/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,9 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] if respond_to?(:wrap_parameters) +end diff --git a/test/dummy/config/locales/en.yml b/test/dummy/config/locales/en.yml new file mode 100644 index 0000000..0653957 --- /dev/null +++ b/test/dummy/config/locales/en.yml @@ -0,0 +1,23 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb new file mode 100644 index 0000000..3f66539 --- /dev/null +++ b/test/dummy/config/routes.rb @@ -0,0 +1,56 @@ +Rails.application.routes.draw do + # The priority is based upon order of creation: first created -> highest priority. + # See how all your routes lay out with "rake routes". + + # You can have the root of your site routed with "root" + # root 'welcome#index' + + # Example of regular route: + # get 'products/:id' => 'catalog#view' + + # Example of named route that can be invoked with purchase_url(id: product.id) + # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase + + # Example resource route (maps HTTP verbs to controller actions automatically): + # resources :products + + # Example resource route with options: + # resources :products do + # member do + # get 'short' + # post 'toggle' + # end + # + # collection do + # get 'sold' + # end + # end + + # Example resource route with sub-resources: + # resources :products do + # resources :comments, :sales + # resource :seller + # end + + # Example resource route with more complex sub-resources: + # resources :products do + # resources :comments + # resources :sales do + # get 'recent', on: :collection + # end + # end + + # Example resource route with concerns: + # concern :toggleable do + # post 'toggle' + # end + # resources :posts, concerns: :toggleable + # resources :photos, concerns: :toggleable + + # Example resource route within a namespace: + # namespace :admin do + # # Directs /admin/products/* to Admin::ProductsController + # # (app/controllers/admin/products_controller.rb) + # resources :products + # end +end diff --git a/test/dummy/config/secrets.yml b/test/dummy/config/secrets.yml new file mode 100644 index 0000000..e9213c0 --- /dev/null +++ b/test/dummy/config/secrets.yml @@ -0,0 +1,22 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rake secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +development: + secret_key_base: 51f457918fc204bef2280de08080b24d6289997cc1af905e47aead42b5e027b6bc27cd6cbd1cb11a34d8df4163d63db2a0ff973acfa11b239a5dd15d6bfb5bfd + +test: + secret_key_base: 1a2d31f4fb35a33e52a69eac67e125b9b1ba5b302e8d3468e60282061a8e74d1a8d977fb88f2eb001aecb99c9c3fbde29e0c7c5ac5d548e1458772ee50ed48e9 + +# Do not keep production secrets in the repository, +# instead read values from the environment. +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/test/dummy/lib/assets/.keep b/test/dummy/lib/assets/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/log/.keep b/test/dummy/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/public/404.html b/test/dummy/public/404.html new file mode 100644 index 0000000..b612547 --- /dev/null +++ b/test/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/422.html b/test/dummy/public/422.html new file mode 100644 index 0000000..a21f82b --- /dev/null +++ b/test/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/500.html b/test/dummy/public/500.html new file mode 100644 index 0000000..061abc5 --- /dev/null +++ b/test/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/favicon.ico b/test/dummy/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/test/helpers/admin/announcements_helper_test.rb b/test/helpers/admin/announcements_helper_test.rb new file mode 100644 index 0000000..a867b12 --- /dev/null +++ b/test/helpers/admin/announcements_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class Admin::AnnouncementsHelperTest < ActionView::TestCase +end diff --git a/test/integration/navigation_test.rb b/test/integration/navigation_test.rb new file mode 100644 index 0000000..eec8c0e --- /dev/null +++ b/test/integration/navigation_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class NavigationTest < ActionDispatch::IntegrationTest + + # test "the truth" do + # assert true + # end +end + diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..1e26a31 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,15 @@ +# Configure Rails Environment +ENV["RAILS_ENV"] = "test" + +require File.expand_path("../dummy/config/environment.rb", __FILE__) +require "rails/test_help" + +Rails.backtrace_cleaner.remove_silencers! + +# Load support files +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } + +# Load fixtures from the engine +if ActiveSupport::TestCase.method_defined?(:fixture_path=) + ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) +end