Merge branch 'master' into polling-views-plus
This commit is contained in:
5
Gemfile
5
Gemfile
@@ -23,6 +23,7 @@ gem 'turbolinks'
|
||||
gem 'sprockets', '~> 3.6.3'
|
||||
|
||||
gem 'devise', '~> 3.5.7'
|
||||
gem 'devise_security_extension'
|
||||
# Use ActiveModel has_secure_password
|
||||
# gem 'bcrypt', '~> 3.1.7'
|
||||
gem 'omniauth'
|
||||
@@ -41,7 +42,7 @@ gem 'ckeditor', '~> 4.2.0'
|
||||
gem 'invisible_captcha', '~> 0.9.1'
|
||||
gem 'cancancan'
|
||||
gem 'social-share-button'
|
||||
gem 'initialjs-rails', '0.2.0.1'
|
||||
gem 'initialjs-rails', '0.2.0.4'
|
||||
gem 'unicorn', '~> 5.1.0'
|
||||
gem 'paranoia'
|
||||
gem 'rinku', require: 'rails_rinku'
|
||||
@@ -79,7 +80,7 @@ group :development, :test do
|
||||
gem 'i18n-tasks'
|
||||
gem 'capistrano', '3.5.0', require: false
|
||||
gem "capistrano-bundler", '1.1.4', require: false
|
||||
gem "capistrano-rails", '1.1.7', require: false
|
||||
gem "capistrano-rails", '1.1.8', require: false
|
||||
gem "capistrano-rvm", require: false
|
||||
gem 'capistrano3-delayed-job', '~> 1.0'
|
||||
gem "bullet"
|
||||
|
||||
40
Gemfile.lock
40
Gemfile.lock
@@ -51,7 +51,7 @@ GEM
|
||||
safely_block (>= 0.1.1)
|
||||
user_agent_parser
|
||||
uuidtools
|
||||
airbrussh (1.0.2)
|
||||
airbrussh (1.1.1)
|
||||
sshkit (>= 1.6.1, != 1.7.0)
|
||||
akami (1.3.1)
|
||||
gyoku (>= 0.4.0)
|
||||
@@ -70,7 +70,7 @@ GEM
|
||||
bullet (5.2.0)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.10.0)
|
||||
byebug (9.0.5)
|
||||
byebug (9.0.6)
|
||||
cancancan (1.15.0)
|
||||
capistrano (3.5.0)
|
||||
airbrussh (>= 1.0.0)
|
||||
@@ -81,8 +81,8 @@ GEM
|
||||
capistrano-bundler (1.1.4)
|
||||
capistrano (~> 3.1)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-harrow (0.5.2)
|
||||
capistrano-rails (1.1.7)
|
||||
capistrano-harrow (0.5.3)
|
||||
capistrano-rails (1.1.8)
|
||||
capistrano (~> 3.1)
|
||||
capistrano-bundler (~> 1.1)
|
||||
capistrano-rvm (0.1.2)
|
||||
@@ -120,7 +120,7 @@ GEM
|
||||
term-ansicolor (~> 1.3)
|
||||
thor (~> 0.19.1)
|
||||
tins (>= 1.6.0, < 2)
|
||||
daemons (1.2.3)
|
||||
daemons (1.2.4)
|
||||
dalli (2.7.6)
|
||||
database_cleaner (1.5.3)
|
||||
debug_inspector (0.0.2)
|
||||
@@ -138,6 +138,9 @@ GEM
|
||||
warden (~> 1.2.3)
|
||||
devise-async (0.10.2)
|
||||
devise (>= 3.2, < 4.0)
|
||||
devise_security_extension (0.10.0)
|
||||
devise (>= 3.0.0, < 4.0)
|
||||
railties (>= 3.2.6, < 5.0)
|
||||
diff-lcs (1.2.5)
|
||||
docile (1.1.5)
|
||||
easy_translate (0.5.0)
|
||||
@@ -176,7 +179,7 @@ GEM
|
||||
geocoder (1.3.7)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
groupdate (3.0.1)
|
||||
groupdate (3.0.2)
|
||||
activesupport (>= 3)
|
||||
gyoku (1.3.1)
|
||||
builder (>= 2.1.2)
|
||||
@@ -196,8 +199,8 @@ GEM
|
||||
parser (>= 2.2.3.0)
|
||||
term-ansicolor (>= 1.3.2)
|
||||
terminal-table (>= 1.5.1)
|
||||
initialjs-rails (0.2.0.1)
|
||||
railties (>= 3.1, < 5.0)
|
||||
initialjs-rails (0.2.0.4)
|
||||
railties (>= 3.1, < 6.0)
|
||||
invisible_captcha (0.9.1)
|
||||
rails
|
||||
jquery-rails (4.1.1)
|
||||
@@ -228,14 +231,14 @@ GEM
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0521)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.9.0)
|
||||
minitest (5.9.1)
|
||||
multi_json (1.12.1)
|
||||
multi_xml (0.5.5)
|
||||
multipart-post (2.0.0)
|
||||
net-scp (1.2.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (3.2.0)
|
||||
newrelic_rpm (3.16.0.318)
|
||||
newrelic_rpm (3.16.3.323)
|
||||
nokogiri (1.6.8)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
pkg-config (~> 1.1.7)
|
||||
@@ -315,7 +318,7 @@ GEM
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
raindrops (0.16.0)
|
||||
rake (11.2.2)
|
||||
rake (11.3.0)
|
||||
redcarpet (3.3.4)
|
||||
referer-parser (0.3.0)
|
||||
request_store (1.3.1)
|
||||
@@ -328,7 +331,7 @@ GEM
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-core (3.5.1)
|
||||
rspec-core (3.5.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
@@ -336,7 +339,7 @@ GEM
|
||||
rspec-mocks (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-rails (3.5.1)
|
||||
rspec-rails (3.5.2)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
@@ -386,7 +389,7 @@ GEM
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
sshkit (1.11.1)
|
||||
sshkit (1.11.3)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
term-ansicolor (1.3.2)
|
||||
@@ -408,7 +411,7 @@ GEM
|
||||
tilt (>= 1.4, < 3)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (3.0.1)
|
||||
uglifier (3.0.2)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicorn (5.1.0)
|
||||
kgio (~> 2.6)
|
||||
@@ -447,7 +450,7 @@ DEPENDENCIES
|
||||
cancancan
|
||||
capistrano (= 3.5.0)
|
||||
capistrano-bundler (= 1.1.4)
|
||||
capistrano-rails (= 1.1.7)
|
||||
capistrano-rails (= 1.1.8)
|
||||
capistrano-rvm
|
||||
capistrano3-delayed-job (~> 1.0)
|
||||
capybara
|
||||
@@ -460,6 +463,7 @@ DEPENDENCIES
|
||||
delayed_job_active_record (~> 4.1.0)
|
||||
devise (~> 3.5.7)
|
||||
devise-async
|
||||
devise_security_extension
|
||||
email_spec
|
||||
factory_girl_rails
|
||||
faker
|
||||
@@ -468,7 +472,7 @@ DEPENDENCIES
|
||||
fuubar
|
||||
groupdate
|
||||
i18n-tasks
|
||||
initialjs-rails (= 0.2.0.1)
|
||||
initialjs-rails (= 0.2.0.4)
|
||||
invisible_captcha (~> 0.9.1)
|
||||
jquery-rails
|
||||
jquery-ui-rails
|
||||
@@ -506,4 +510,4 @@ DEPENDENCIES
|
||||
whenever
|
||||
|
||||
BUNDLED WITH
|
||||
1.12.5
|
||||
1.13.1
|
||||
|
||||
@@ -34,7 +34,6 @@ cd consul
|
||||
bundle install
|
||||
cp config/database.yml.example config/database.yml
|
||||
cp config/secrets.yml.example config/secrets.yml
|
||||
rake db:create
|
||||
bin/rake db:setup
|
||||
bin/rake db:dev_seed
|
||||
RAILS_ENV=test rake db:setup
|
||||
|
||||
@@ -34,7 +34,6 @@ cd consul
|
||||
bundle install
|
||||
cp config/database.yml.example config/database.yml
|
||||
cp config/secrets.yml.example config/secrets.yml
|
||||
rake db:create
|
||||
bin/rake db:setup
|
||||
bin/rake db:dev_seed
|
||||
RAILS_ENV=test rake db:setup
|
||||
|
||||
Binary file not shown.
@@ -54,4 +54,8 @@
|
||||
<glyph glyph-name="arrow-down" unicode="R" d="M402 311c0-5-2-9-5-13l-128-128c-4-4-8-5-13-5-5 0-9 1-13 5l-128 128c-3 4-5 8-5 13 0 5 2 9 5 13 4 3 8 5 13 5l256 0c5 0 9-2 13-5 3-4 5-8 5-13z"/>
|
||||
<glyph glyph-name="arrow-left" unicode="T" d="M347 384l0-256c0-5-1-9-5-13-4-3-8-5-13-5-5 0-9 2-13 5l-128 128c-3 4-5 8-5 13 0 5 2 9 5 13l128 128c4 3 8 5 13 5 5 0 9-2 13-5 4-4 5-8 5-13z"/>
|
||||
<glyph glyph-name="arrow-right" unicode="U" d="M329 256c0-5-2-9-5-13l-128-128c-4-3-8-5-13-5-5 0-9 2-13 5-4 4-5 8-5 13l0 256c0 5 1 9 5 13 4 3 8 5 13 5 5 0 9-2 13-5l128-128c3-4 5-8 5-13z"/>
|
||||
<glyph glyph-name="check-circle" unicode="V" d="M256 480c-124 0-224-100-224-224 0-124 100-224 224-224 124 0 224 100 224 224 0 124-100 224-224 224z m115-149l-139-179c-1-1-3-3-5-3-3 0-4 1-5 3-2 1-79 76-79 76l-2 1c0 1-1 2-1 3 0 2 1 3 1 4 1 0 1 0 1 1 8 8 24 24 25 25 1 2 2 3 4 3 3 0 5-2 6-3 1-1 45-43 45-43l111 143c1 0 2 1 4 1 1 0 2 0 3-1l31-24c0-1 1-3 1-4 0-1 0-2-1-3z"/>
|
||||
<glyph glyph-name="arrow-top" unicode="W" d="M402 165c0-5-2-10-5-13-4-4-8-6-13-6l-256 0c-5 0-9 2-13 6-3 3-5 8-5 13 0 5 2 9 5 12l128 128c4 4 8 6 13 6 5 0 9-2 13-6l128-128c3-3 5-7 5-12z"/>
|
||||
<glyph glyph-name="help-1" unicode="X" d="M345 435c-27 21-58 28-98 28-29 0-55-6-75-20-30-20-44-54-44-108l77 0c0 14-2 30 7 43 8 13 20 24 40 24 20 0 31-6 41-18 8-11 11-23 11-36 0-12-5-22-12-32-4-5-9-10-15-15 0 0-42-25-56-48-11-18-15-40-16-66 0-2 0-5 7-5 7 0 56 0 62 0 6 0 7 4 7 6 0 9 2 24 3 29 4 11 10 20 20 28l21 14c18 15 33 26 40 36 11 15 19 34 19 57 0 36-13 64-39 83z m-103-293c-26 1-47-17-48-46-1-28 19-46 45-47 27-1 48 17 49 45 1 28-19 47-46 48z"/>
|
||||
<glyph glyph-name="checkmark-circle" unicode="Y" d="M171 296l-29-30 93-93 208 208-29 29-179-178z m251-40c0-92-74-166-166-166-92 0-166 74-166 166 0 92 74 166 166 166 16 0 31-2 46-6l32 32c-24 11-50 16-78 16-114 0-208-94-208-208 0-114 94-208 208-208 114 0 208 94 208 208z"/>
|
||||
</font></defs></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Binary file not shown.
BIN
app/assets/images/ballot.gif
Normal file
BIN
app/assets/images/ballot.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
app/assets/images/ballot_tiny.gif
Normal file
BIN
app/assets/images/ballot_tiny.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -172,3 +172,6 @@
|
||||
.icon-arrow-right:before {
|
||||
content: "\55";
|
||||
}
|
||||
.icon-checkmark-circle:before {
|
||||
content: "\59";
|
||||
}
|
||||
|
||||
@@ -732,6 +732,56 @@ form {
|
||||
// 07. Callout
|
||||
// -----------
|
||||
|
||||
.callout-slide {
|
||||
animation-duration: 1s;
|
||||
-webkit-animation-duration: 1s;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-name: slide;
|
||||
-webkit-animation-name: slide;
|
||||
}
|
||||
|
||||
@-webkit-keyframes slide {
|
||||
from {
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide {
|
||||
from {
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.notice-container {
|
||||
min-width: $line-height*12;
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
top: 24px;
|
||||
|
||||
.notice {
|
||||
height: $line-height*4;
|
||||
|
||||
.notice-text {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.callout {
|
||||
font-size: $small-font-size;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// 03. Show participation
|
||||
// 04. List participation
|
||||
// 05. Featured
|
||||
// 06. Proposals successfull
|
||||
//
|
||||
|
||||
// 01. Votes and supports
|
||||
@@ -269,6 +270,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
@include supports;
|
||||
background: none;
|
||||
border-top: 0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
border-left: 1px solid $border;
|
||||
margin: $line-height rem-calc(-25) 0 rem-calc(12);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: $small-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// 02. New participation
|
||||
// ---------------------
|
||||
|
||||
@@ -548,14 +564,14 @@
|
||||
|
||||
.debates-list, .proposals-list, .investment-projects-list {
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
margin-bottom: rem-calc(48);
|
||||
}
|
||||
}
|
||||
|
||||
.investment-projects-list {
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
min-height: $line-height*15;
|
||||
}
|
||||
}
|
||||
@@ -574,7 +590,7 @@
|
||||
min-height: rem-calc(192);
|
||||
padding: rem-calc(12) rem-calc(12) 0 rem-calc(12);
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
margin-bottom: rem-calc(-1);
|
||||
padding-bottom: rem-calc(12);
|
||||
}
|
||||
@@ -732,7 +748,7 @@
|
||||
border: 1px solid $votes-border;
|
||||
margin: 0 rem-calc(-12);
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
margin: 0 rem-calc(-25) 0 rem-calc(12);
|
||||
@@ -750,7 +766,7 @@
|
||||
right: -1px;
|
||||
border-width: 13px 13px 0 0;
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
@@ -762,7 +778,7 @@
|
||||
padding-top: rem-calc(12);
|
||||
vertical-align: top;
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
display: block;
|
||||
float: none;
|
||||
line-height: $line-height*2;
|
||||
@@ -771,7 +787,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
.like, .unlike {
|
||||
|
||||
span.percentage {
|
||||
@@ -790,7 +806,7 @@
|
||||
border: 1px solid $proposals-border;
|
||||
margin: 0 rem-calc(-12);
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
margin: 0 rem-calc(-25) 0 rem-calc(12);
|
||||
@@ -808,7 +824,7 @@
|
||||
right: -1px;
|
||||
border-width: 13px 13px 0 0;
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
@@ -819,7 +835,7 @@
|
||||
padding-top: rem-calc(12);
|
||||
vertical-align: top;
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
display: block;
|
||||
float: none;
|
||||
margin-left: 0;
|
||||
@@ -840,7 +856,7 @@
|
||||
min-height: rem-calc(180);
|
||||
padding-top: 0;
|
||||
|
||||
@include breakpoint(small) {
|
||||
@include breakpoint(medium) {
|
||||
padding-top: $line-height*1.5;
|
||||
}
|
||||
|
||||
@@ -929,7 +945,8 @@
|
||||
// 05. Featured
|
||||
// ------------
|
||||
|
||||
.featured-debates, .featured-proposals {
|
||||
.featured-debates, .featured-proposals,
|
||||
.proposals-ballot, .proposals-ballot-list {
|
||||
padding: $line-height/2 0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
@@ -1029,3 +1046,112 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 06. Proposals successfull
|
||||
// -------------------------
|
||||
|
||||
.dark-heading {
|
||||
background: #2D3E50;
|
||||
color: white;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
padding-bottom: $line-height;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.title {
|
||||
color: #FFD200;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
background: #314253;
|
||||
padding-top: $line-height;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
border-top: rem-calc(6) solid #FFD200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.featured-proposals-ballot-banner {
|
||||
background: #2D3E50 image-url("ballot_tiny.gif") no-repeat;
|
||||
background-position: 75% 0;
|
||||
position: relative;
|
||||
|
||||
h2, a:hover h2 {
|
||||
color: #FFD200 !important;
|
||||
}
|
||||
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
|
||||
@include breakpoint(medium) {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
@include breakpoint(large) {
|
||||
background: #2D3E50 image-url("ballot.gif") no-repeat;
|
||||
background-position: 90% 0;
|
||||
}
|
||||
}
|
||||
|
||||
.featured-proposals-ballot-banner,
|
||||
.successfull .panel {
|
||||
|
||||
.icon-successfull {
|
||||
border-right: 60px solid #FFD200;
|
||||
border-top: 0;
|
||||
border-bottom: 60px solid transparent;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 0;
|
||||
|
||||
&:after {
|
||||
color: #1B254C;
|
||||
content: "\59";
|
||||
font-family: "icons" !important;
|
||||
left: 34px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.proposals-ballot-list {
|
||||
|
||||
.proposal-sucessfull {
|
||||
background: white;
|
||||
border-top: 1px solid $border;
|
||||
padding: $line-height 0;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.successfull {
|
||||
|
||||
.panel {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
@include supports;
|
||||
background: none;
|
||||
border-top: 0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
border-left: 1px solid $border;
|
||||
margin: $line-height rem-calc(-25) 0 rem-calc(12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ module CommentableActions
|
||||
|
||||
@tag_cloud = tag_cloud
|
||||
@banners = Banner.with_active
|
||||
|
||||
|
||||
set_resource_votes(@resources)
|
||||
set_resources_instance
|
||||
end
|
||||
|
||||
@@ -22,6 +22,7 @@ class DebatesController < ApplicationController
|
||||
|
||||
def index_customization
|
||||
@featured_debates = @debates.featured
|
||||
@proposal_successfull_exists = Proposal.successfull.exists?
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
8
app/controllers/proposal_ballots_controller.rb
Normal file
8
app/controllers/proposal_ballots_controller.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class ProposalBallotsController < ApplicationController
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
@proposal_ballots = Proposal.successfull.sort_by_confidence_score
|
||||
end
|
||||
|
||||
end
|
||||
@@ -12,7 +12,7 @@ class ProposalsController < ApplicationController
|
||||
|
||||
invisible_captcha only: [:create, :update], honeypot: :subtitle
|
||||
|
||||
has_orders %w{hot_score confidence_score created_at relevance}, only: :index
|
||||
has_orders %w{hot_score confidence_score created_at relevance archival_date}, only: :index
|
||||
has_orders %w{most_voted newest oldest}, only: :show
|
||||
|
||||
load_and_authorize_resource
|
||||
@@ -26,8 +26,10 @@ class ProposalsController < ApplicationController
|
||||
end
|
||||
|
||||
def index_customization
|
||||
discard_archived
|
||||
load_retired
|
||||
load_featured
|
||||
load_proposal_ballots
|
||||
load_featured unless @proposal_successfull_exists
|
||||
end
|
||||
|
||||
def vote
|
||||
@@ -80,6 +82,10 @@ class ProposalsController < ApplicationController
|
||||
@featured_proposals_votes = current_user ? current_user.proposal_votes(proposals) : {}
|
||||
end
|
||||
|
||||
def discard_archived
|
||||
@resources = @resources.not_archived unless @current_order == "archival_date"
|
||||
end
|
||||
|
||||
def load_retired
|
||||
if params[:retired].present?
|
||||
@resources = @resources.retired
|
||||
@@ -90,11 +96,15 @@ class ProposalsController < ApplicationController
|
||||
end
|
||||
|
||||
def load_featured
|
||||
@featured_proposals = Proposal.all.sort_by_confidence_score.limit(3) if (!@advanced_search_terms && @search_terms.blank? && @tag_filter.blank? && params[:retired].blank?)
|
||||
@featured_proposals = Proposal.not_archived.sort_by_confidence_score.limit(3) if (!@advanced_search_terms && @search_terms.blank? && @tag_filter.blank? && params[:retired].blank?)
|
||||
if @featured_proposals.present?
|
||||
set_featured_proposal_votes(@featured_proposals)
|
||||
@resources = @resources.where('proposals.id NOT IN (?)', @featured_proposals.map(&:id))
|
||||
end
|
||||
end
|
||||
|
||||
def load_proposal_ballots
|
||||
@proposal_successfull_exists = Proposal.successfull.exists?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -44,9 +44,13 @@ class Proposal < ActiveRecord::Base
|
||||
scope :sort_by_random, -> { reorder("RANDOM()") }
|
||||
scope :sort_by_relevance, -> { all }
|
||||
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
|
||||
scope :sort_by_archival_date, -> { archived.sort_by_confidence_score }
|
||||
scope :archived, -> { where("proposals.created_at <= ?", Setting["months_to_archive_proposals"].to_i.months.ago)}
|
||||
scope :not_archived, -> { where("proposals.created_at > ?", Setting["months_to_archive_proposals"].to_i.months.ago)}
|
||||
scope :last_week, -> { where("proposals.created_at >= ?", 7.days.ago)}
|
||||
scope :retired, -> { where.not(retired_at: nil) }
|
||||
scope :not_retired, -> { where(retired_at: nil) }
|
||||
scope :successfull, -> { where("cached_votes_up + physical_votes >= ?", Proposal.votes_needed_for_success)}
|
||||
|
||||
def to_param
|
||||
"#{id}-#{title}".parameterize
|
||||
@@ -119,7 +123,7 @@ class Proposal < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def register_vote(user, vote_value)
|
||||
if votable_by?(user)
|
||||
if votable_by?(user) && !archived?
|
||||
vote_by(voter: user, vote: vote_value)
|
||||
end
|
||||
end
|
||||
@@ -155,6 +159,14 @@ class Proposal < ActiveRecord::Base
|
||||
Setting['votes_for_proposal_success'].to_i
|
||||
end
|
||||
|
||||
def successfull?
|
||||
total_votes >= Proposal.votes_needed_for_success
|
||||
end
|
||||
|
||||
def archived?
|
||||
self.created_at <= Setting["months_to_archive_proposals"].to_i.months.ago
|
||||
end
|
||||
|
||||
def notifications
|
||||
proposal_notifications
|
||||
end
|
||||
|
||||
@@ -2,8 +2,8 @@ class User < ActiveRecord::Base
|
||||
|
||||
include Verification
|
||||
|
||||
devise :database_authenticatable, :registerable, :confirmable,
|
||||
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :async
|
||||
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable,
|
||||
:trackable, :validatable, :omniauthable, :async, :password_expirable, :secure_validatable
|
||||
|
||||
acts_as_voter
|
||||
acts_as_paranoid column: :hidden_at
|
||||
|
||||
@@ -29,7 +29,11 @@
|
||||
<%= render "shared/banner" %>
|
||||
<% end %>
|
||||
|
||||
<% unless @tag_filter || @search_terms || !has_featured? %>
|
||||
<% if @proposal_successfull_exists %>
|
||||
<%= render "proposals/proposal_ballots_banner" %>
|
||||
<% end %>
|
||||
|
||||
<% unless @tag_filter || @search_terms || !has_featured? || @proposal_ballots.present? || @proposal_successfull_exists %>
|
||||
<%= render "featured_debates" %>
|
||||
<% end %>
|
||||
|
||||
|
||||
13
app/views/devise/password_expired/show.html.erb
Normal file
13
app/views/devise/password_expired/show.html.erb
Normal file
@@ -0,0 +1,13 @@
|
||||
<h2><%= t("devise.password_expired.expire_password") %></h2>
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => [resource_name, :password_expired], :html => { :method => :put }) do |f| %>
|
||||
|
||||
<%= f.password_field :current_password %></p>
|
||||
|
||||
<%= f.label t("devise.password_expired.new_password") %>
|
||||
<%= f.password_field :password, label: false %></p>
|
||||
|
||||
<%= f.password_field :password_confirmation %></p>
|
||||
|
||||
<p><%= f.submit t("devise.password_expired.change_password") %></p>
|
||||
<% end %>
|
||||
@@ -13,6 +13,6 @@
|
||||
</div>
|
||||
|
||||
<h1><%= @direct_message.title %></h1>
|
||||
<p><%= @direct_message.body %></p>
|
||||
<p><%= simple_format text_with_links(@direct_message.body), {}, sanitize: false %></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<% flash.each do |flash_key, flash_message| %>
|
||||
<div id="<%= flash_key %>" data-alert class="row" data-closable>
|
||||
<div class="callout <%= flash_key %>">
|
||||
<div id="<%= flash_key %>" data-alert class="notice-container callout-slide" data-closable>
|
||||
<div class="callout notice <%= flash_key %>">
|
||||
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<%= flash_message %>
|
||||
<div class="notice-text">
|
||||
<%= flash_message %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<%= @direct_message.title %>
|
||||
</h1>
|
||||
|
||||
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
|
||||
<%= @direct_message.body %>
|
||||
</p>
|
||||
<div style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
|
||||
<%= simple_format text_with_links(@direct_message.body), {}, sanitize: false %>
|
||||
</div>
|
||||
|
||||
<table style="width: 100%; border-top: 1px solid #DEE0E3; margin-top: 60px;">
|
||||
<tbody>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<%= @direct_message.title %>
|
||||
</h2>
|
||||
|
||||
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
|
||||
<%= @direct_message.body %>
|
||||
</p>
|
||||
<div style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
|
||||
<%= simple_format text_with_links(@direct_message.body), {}, sanitize: false %>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
13
app/views/proposal_ballots/_successfull_proposal.html.erb
Normal file
13
app/views/proposal_ballots/_successfull_proposal.html.erb
Normal file
@@ -0,0 +1,13 @@
|
||||
<div id="<%= dom_id(proposal) %>" class="proposal-sucessfull">
|
||||
<h3><%= link_to proposal.title, proposal %></h3>
|
||||
<div class="info">
|
||||
<% if proposal.author.hidden? || proposal.author.erased? %>
|
||||
<%= t("proposals.show.author_deleted") %>
|
||||
<% else %>
|
||||
<%= proposal.author.name %>
|
||||
<% end %>
|
||||
|
||||
<span class="bullet"> • </span>
|
||||
<%= l proposal.created_at.to_date %>
|
||||
</div>
|
||||
</div>
|
||||
35
app/views/proposal_ballots/index.html.erb
Normal file
35
app/views/proposal_ballots/index.html.erb
Normal file
@@ -0,0 +1,35 @@
|
||||
<div class="expanded no-margin-top margin-bottom dark-heading">
|
||||
<div class="row" data-equalizer>
|
||||
<div class="small-12 medium-6 column padding" data-equalizer-watch>
|
||||
<h2>
|
||||
<%= t("proposal_ballots.title") %>
|
||||
</h2>
|
||||
<p>
|
||||
<%= t("proposal_ballots.description_html").html_safe %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-4 column info" data-equalizer-watch>
|
||||
<p class="title"><strong><%= t("proposal_ballots.date_title") %></strong></p>
|
||||
<h3><%= t("proposal_ballots.date") %></h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<% if @proposal_ballots.present? %>
|
||||
<div class="proposals-ballot-list">
|
||||
<% @proposal_ballots.each do |proposal_for_vote| %>
|
||||
<%= render "successfull_proposal", proposal: proposal_for_vote %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<p>
|
||||
<%= t("proposal_ballots.nothing_to_vote") %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@@ -1,10 +1,12 @@
|
||||
<div id="<%= dom_id(proposal) %>" class="proposal clear" data-type="proposal">
|
||||
<div id="<%= dom_id(proposal) %>"
|
||||
class="proposal clear <%= ("successfull" if proposal.total_votes > Proposal.votes_needed_for_success) %>"
|
||||
data-type="proposal">
|
||||
<div class="panel">
|
||||
<div class="icon-successfull"></div>
|
||||
<div class="row">
|
||||
|
||||
<div class="small-12 medium-9 column">
|
||||
<div class="proposal-content">
|
||||
|
||||
<% cache [locale_and_user_status(proposal), 'index', proposal, proposal.author] do %>
|
||||
<span class="label-proposal float-left"><%= t("proposals.proposal.proposal") %></span>
|
||||
<span class="icon-proposals"></span>
|
||||
@@ -50,11 +52,26 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(proposal) %>_votes" class="small-12 medium-3 column text-center">
|
||||
<%= render 'votes',
|
||||
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: 'yes') } %>
|
||||
<div id="<%= dom_id(proposal) %>_votes" class="small-12 medium-3 column">
|
||||
<% if proposal.successfull? %>
|
||||
<div class="message">
|
||||
<p>
|
||||
<%= t("proposal_ballots.successfull",
|
||||
voting: link_to(t("proposal_ballots.voting"), proposal_ballots_path)).html_safe %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif proposal.archived? %>
|
||||
<div class="message">
|
||||
<strong><%= t("proposals.proposal.supports", count: proposal.total_votes) %></strong>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center">
|
||||
<%= render 'votes',
|
||||
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: 'yes') } %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
9
app/views/proposals/_proposal_ballots_banner.html.erb
Normal file
9
app/views/proposals/_proposal_ballots_banner.html.erb
Normal file
@@ -0,0 +1,9 @@
|
||||
<div id="next-voting" class="row featured-proposals-ballot-banner">
|
||||
<%= link_to proposal_ballots_path do %>
|
||||
<div class="small-12 column padding">
|
||||
<div class="icon-successfull"></div>
|
||||
<h2><%= t("proposal_ballots.featured_title") %></h2>
|
||||
<p><%= t("proposal_ballots.info") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -30,8 +30,10 @@
|
||||
<% if has_banners %>
|
||||
<%= render "shared/banner" %>
|
||||
<% end %>
|
||||
|
||||
<% if @featured_proposals.present? %>
|
||||
|
||||
<% if @proposal_successfull_exists %>
|
||||
<%= render "proposal_ballots_banner" %>
|
||||
<% elsif @featured_proposals.present? %>
|
||||
<div id="featured-proposals" class="row featured-proposals">
|
||||
<div class="small-12 column">
|
||||
<h2>
|
||||
@@ -52,8 +54,10 @@
|
||||
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button expanded' %>
|
||||
</div>
|
||||
|
||||
<%= render partial: 'proposals/proposal', collection: @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
<div id="proposals-list">
|
||||
<%= render partial: 'proposals/proposal', collection: @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-3 column">
|
||||
|
||||
@@ -102,11 +102,23 @@
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h3><%= t("votes.supports") %></h3>
|
||||
<div class="text-center">
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<%= render 'votes',
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
|
||||
</div>
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<% if @proposal.successfull? %>
|
||||
<p>
|
||||
<%= t("proposal_ballots.successfull",
|
||||
voting: link_to(t("proposal_ballots.voting"), proposal_ballots_path)).html_safe %>
|
||||
</p>
|
||||
<% elsif @proposal.archived? %>
|
||||
<p class="text-center">
|
||||
<strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong>
|
||||
</p>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
<% else %>
|
||||
<div class="text-center">
|
||||
<%= render 'votes',
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div id="social-share" class="sidebar-divider"></div>
|
||||
<h3><%= t("proposals.show.share") %></h3>
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
<li>
|
||||
<%= link_to t("layouts.header.proposals"), proposals_path, class: ("active" if controller_name == "proposals"), accesskey: "p" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.proposal_ballot"), proposal_ballots_path, class: ("active" if controller_name == "proposal_ballots"), accesskey: "v" %>
|
||||
</li>
|
||||
<% if feature?(:spending_proposals) %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.spending_proposals"), spending_proposals_path, class: ("active" if controller_name == "spending_proposals"), accesskey: "s" %>
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path("../spring", __FILE__)
|
||||
rescue LoadError
|
||||
end
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
|
||||
4
bin/rake
4
bin/rake
@@ -1,8 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path("../spring", __FILE__)
|
||||
rescue LoadError
|
||||
end
|
||||
require_relative '../config/boot'
|
||||
require 'rake'
|
||||
Rake.application.run
|
||||
|
||||
16
bin/rspec
16
bin/rspec
@@ -1,9 +1,5 @@
|
||||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path('../spring', __FILE__)
|
||||
rescue LoadError => e
|
||||
raise unless e.message.include?('spring')
|
||||
end
|
||||
# frozen_string_literal: true
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
@@ -11,11 +7,11 @@ end
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
load Gem.bin_path('rspec-core', 'rspec')
|
||||
load Gem.bin_path("rspec-core", "rspec")
|
||||
|
||||
24
bin/spring
24
bin/spring
@@ -1,15 +1,17 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'spring' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
# This file loads spring without using Bundler, in order to be fast.
|
||||
# It gets overwritten when you run the `spring binstub` command.
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
unless defined?(Spring)
|
||||
require 'rubygems'
|
||||
require 'bundler'
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
|
||||
Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq }
|
||||
gem 'spring', match[1]
|
||||
require 'spring/binstub'
|
||||
end
|
||||
end
|
||||
load Gem.bin_path("spring", "spring")
|
||||
|
||||
@@ -24,7 +24,6 @@ module Consul
|
||||
config.i18n.available_locales = [:en, :es]
|
||||
|
||||
# Add the new directories to the locales load path
|
||||
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
|
||||
|
||||
config.assets.paths << Rails.root.join("app", "assets", "fonts")
|
||||
|
||||
@@ -44,6 +43,7 @@ module Consul
|
||||
config.autoload_paths << "#{Rails.root}/app/controllers/custom"
|
||||
config.autoload_paths << "#{Rails.root}/app/models/custom"
|
||||
config.paths['app/views'].unshift(Rails.root.join('app', 'views', 'custom'))
|
||||
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', 'custom', '*.{rb,yml}')]
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -102,6 +102,7 @@ ignore_missing:
|
||||
- 'errors.messages.taken'
|
||||
- 'devise.failure.invalid'
|
||||
- 'devise.registrations.destroyed'
|
||||
- 'devise.password_expired.*'
|
||||
|
||||
## Consider these keys used:
|
||||
ignore_unused:
|
||||
|
||||
71
config/initializers/devise_security_extension.rb
Normal file
71
config/initializers/devise_security_extension.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
Devise.setup do |config|
|
||||
# ==> Security Extension
|
||||
# Configure security extension for devise
|
||||
|
||||
# Should the password expire (e.g 3.months)
|
||||
# config.expire_password_after = false
|
||||
config.expire_password_after = 1.year
|
||||
|
||||
# Need 1 char of A-Z, a-z and 0-9
|
||||
# config.password_regex = /(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])/
|
||||
|
||||
# How many passwords to keep in archive
|
||||
#config.password_archiving_count = 5
|
||||
|
||||
# Deny old password (true, false, count)
|
||||
# config.deny_old_passwords = true
|
||||
|
||||
# enable email validation for :secure_validatable. (true, false, validation_options)
|
||||
# dependency: need an email validator like rails_email_validator
|
||||
# config.email_validation = true
|
||||
# captcha integration for recover form
|
||||
# config.captcha_for_recover = true
|
||||
|
||||
# captcha integration for sign up form
|
||||
# config.captcha_for_sign_up = true
|
||||
|
||||
# captcha integration for sign in form
|
||||
# config.captcha_for_sign_in = true
|
||||
|
||||
# captcha integration for unlock form
|
||||
# config.captcha_for_unlock = true
|
||||
|
||||
# captcha integration for confirmation form
|
||||
# config.captcha_for_confirmation = true
|
||||
|
||||
# Time period for account expiry from last_activity_at
|
||||
# config.expire_after = 90.days
|
||||
end
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
module PasswordExpirable
|
||||
def need_change_password?
|
||||
self.administrator? && password_expired?
|
||||
end
|
||||
|
||||
def password_expired?
|
||||
self.password_changed_at < self.expire_password_after.ago
|
||||
end
|
||||
end
|
||||
|
||||
module SecureValidatable
|
||||
def self.included(base)
|
||||
base.extend ClassMethods
|
||||
assert_secure_validations_api!(base)
|
||||
base.class_eval do
|
||||
validate :current_equal_password_validation
|
||||
end
|
||||
end
|
||||
|
||||
def current_equal_password_validation
|
||||
if !self.new_record? && !self.encrypted_password_change.nil? && !self.erased?
|
||||
dummy = self.class.new
|
||||
dummy.encrypted_password = self.encrypted_password_change.first
|
||||
dummy.password_salt = self.password_salt_change.first if self.respond_to? :password_salt_change and not self.password_salt_change.nil?
|
||||
self.errors.add(:password, :equal_to_current_password) if dummy.valid_password?(self.password)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -54,6 +54,7 @@ en:
|
||||
username: "Username"
|
||||
password_confirmation: "Password confirmation"
|
||||
password: "Password"
|
||||
current_password: "Current password"
|
||||
phone_number: "Phone number"
|
||||
official_position: "Official position"
|
||||
official_level: "Official level"
|
||||
|
||||
@@ -54,6 +54,7 @@ es:
|
||||
username: "Nombre de usuario"
|
||||
password_confirmation: "Confirmación de contraseña"
|
||||
password: "Contraseña"
|
||||
current_password: "Contraseña actual"
|
||||
phone_number: "Teléfono"
|
||||
official_position: "Cargo público"
|
||||
official_level: "Nivel del cargo"
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
en:
|
||||
devise:
|
||||
password_expired:
|
||||
expire_password: "Password expired"
|
||||
change_required: "Your password is expired"
|
||||
change_password: "Change your password"
|
||||
new_password: "New password"
|
||||
updated: "Password successfully updated"
|
||||
confirmations:
|
||||
confirmed: "Your account has been confirmed."
|
||||
send_instructions: "In a few minutes you will receive an email containing instructions on how to reset your password."
|
||||
@@ -62,3 +68,4 @@ en:
|
||||
not_saved:
|
||||
one: "1 error prevented this %{resource} from being saved:"
|
||||
other: "%{count} errors prevented this %{resource} from being saved:"
|
||||
equal_to_current_password: "must be different than the current password."
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
es:
|
||||
devise:
|
||||
password_expired:
|
||||
expire_password: "Contraseña caducada"
|
||||
change_required: "Tu contraseña ha caducado"
|
||||
change_password: "Cambia tu contraseña"
|
||||
new_password: "Nueva contraseña"
|
||||
updated: "Contraseña actualizada con éxito"
|
||||
confirmations:
|
||||
confirmed: "Tu cuenta ha sido confirmada. Por favor autentifícate con tu red social o tu usuario y contraseña"
|
||||
send_instructions: "Recibirás un correo electrónico en unos minutos con instrucciones sobre cómo restablecer tu contraseña."
|
||||
@@ -60,3 +66,4 @@ es:
|
||||
not_saved:
|
||||
one: "1 error impidió que este %{resource} fuera guardado:"
|
||||
other: "%{count} errores impidieron que este %{resource} fuera guardado:"
|
||||
equal_to_current_password: "debe ser diferente a la contraseña actual"
|
||||
|
||||
@@ -210,6 +210,7 @@ en:
|
||||
open_data: Open data
|
||||
open_gov: Open government
|
||||
proposals: Proposals
|
||||
proposal_ballot: Voting
|
||||
see_all: See proposals
|
||||
spending_proposals: Spending proposals
|
||||
legislation:
|
||||
@@ -302,6 +303,7 @@ en:
|
||||
hot_score: most active
|
||||
most_commented: most commented
|
||||
relevance: relevance
|
||||
archival_date: Archived
|
||||
retired_proposals: Retired proposals
|
||||
retired_proposals_link: "Proposals retired by the author"
|
||||
retired_links:
|
||||
@@ -351,6 +353,7 @@ en:
|
||||
zero: No supports
|
||||
supports_necessary: "%{number} supports needed"
|
||||
total_percent: 100%
|
||||
archived: "This proposal has been archived and can't collect supports."
|
||||
show:
|
||||
author_deleted: User deleted
|
||||
code: 'Proposal code:'
|
||||
@@ -372,6 +375,17 @@ en:
|
||||
update:
|
||||
form:
|
||||
submit_button: Save changes
|
||||
proposal_ballots:
|
||||
title: "Votings"
|
||||
description_html: "The following citizen proposals that have reached the <strong>required supports</strong> and will be voted."
|
||||
date_title: "Dates of participation"
|
||||
date: "Soon we'll announce the date of vote these proposals."
|
||||
successfull: "This proposal has reached the required supports and will be voted in the %{voting}."
|
||||
voting: "next voting"
|
||||
featured_title: "#NextVoting"
|
||||
nothing_to_vote: "There is nothing to vote at the moment."
|
||||
info: "New proposals that have reached the voting phase."
|
||||
button: "I want to decide"
|
||||
proposal_notifications:
|
||||
new:
|
||||
title: "Send message"
|
||||
|
||||
@@ -210,6 +210,7 @@ es:
|
||||
open_data: Datos abiertos
|
||||
open_gov: Gobierno %{open}
|
||||
proposals: Propuestas
|
||||
proposal_ballot: Votaciones
|
||||
see_all: Ver propuestas
|
||||
spending_proposals: Presupuestos ciudadanos
|
||||
legislation:
|
||||
@@ -302,6 +303,7 @@ es:
|
||||
hot_score: Más activas hoy
|
||||
most_commented: Más comentadas
|
||||
relevance: Más relevantes
|
||||
archival_date: Archivadas
|
||||
retired_proposals: Propuestas retiradas
|
||||
retired_proposals_link: "Propuestas retiradas por sus autores"
|
||||
retired_links:
|
||||
@@ -351,6 +353,7 @@ es:
|
||||
zero: Sin apoyos
|
||||
supports_necessary: "%{number} apoyos necesarios"
|
||||
total_percent: 100%
|
||||
archived: "Esta propuesta ha sido archivada y ya no puede recoger apoyos."
|
||||
show:
|
||||
author_deleted: Usuario eliminado
|
||||
code: 'Código de la propuesta:'
|
||||
@@ -372,6 +375,17 @@ es:
|
||||
update:
|
||||
form:
|
||||
submit_button: Guardar cambios
|
||||
proposal_ballots:
|
||||
title: "Votaciones"
|
||||
description_html: "Las siguientes propuestas ciudadanas han alcanzado el <strong>número de apoyos necesarios</strong> y pasarán a votación."
|
||||
date_title: "Fechas de participación"
|
||||
date: "En breve anunciaremos la fecha de votación de estas propuestas."
|
||||
successfull: "Esta propuesta ha alcanzado los apoyos necesarios y pasará a la %{voting}."
|
||||
voting: "próxima votación"
|
||||
featured_title: "#PróximaVotación"
|
||||
nothing_to_vote: "No hay nada que votar en este momento."
|
||||
info: "Nuevas propuestas ciudadanas han llegado a la fase de votación."
|
||||
button: "Quiero decidir"
|
||||
proposal_notifications:
|
||||
new:
|
||||
title: "Enviar mensaje"
|
||||
|
||||
@@ -11,9 +11,21 @@ en:
|
||||
max_votes_for_debate_edit: "Number of votes from which a Debate can no longer be edited"
|
||||
proposal_code_prefix: "Prefix for Proposal codes"
|
||||
votes_for_proposal_success: "Number of votes necessary for approval of a Proposal"
|
||||
months_to_archive_proposals: "Months to archive Proposals"
|
||||
email_domain_for_officials: "Email domain for public officials"
|
||||
per_page_code: "Code to be included on every page"
|
||||
twitter_handle: "Twitter handle"
|
||||
twitter_hashtag: "Twitter hashtag"
|
||||
facebook_handle: "Facebook handle"
|
||||
youtube_handle: "Youtube handle"
|
||||
blog_url: "Blog URL"
|
||||
url: "Main URL"
|
||||
org_name: "Organization"
|
||||
place_name: "Place"
|
||||
feature:
|
||||
twitter_login: Twitter login
|
||||
facebook_login: Facebook login
|
||||
google_login: Google login
|
||||
debates: Debates
|
||||
spending_proposals: Investment projects
|
||||
spending_proposal_features:
|
||||
|
||||
@@ -11,9 +11,21 @@ es:
|
||||
max_votes_for_debate_edit: "Número de votos en que un Debate deja de poderse editar"
|
||||
proposal_code_prefix: "Prefijo para los códigos de Propuestas"
|
||||
votes_for_proposal_success: "Número de votos necesarios para aprobar una Propuesta"
|
||||
months_to_archive_proposals: "Meses para archivar las Propuestas"
|
||||
email_domain_for_officials: "Dominio de email para cargos públicos"
|
||||
per_page_code: "Código a incluir en cada página"
|
||||
twitter_handle: "Usuario de Twitter"
|
||||
twitter_hashtag: "Hashtag para Twitter"
|
||||
facebook_handle: "Identificador de Facebook"
|
||||
youtube_handle: "Usuario de Youtube"
|
||||
blog_url: "URL del blog"
|
||||
url: "URL general de la web"
|
||||
org_name: "Nombre de la organización"
|
||||
place_name: "Nombre del lugar"
|
||||
feature:
|
||||
twitter_login: Registro con Twitter
|
||||
facebook_login: Registro con Facebook
|
||||
google_login: Registro con Google
|
||||
debates: Debates
|
||||
spending_proposals: Propuestas de inversión
|
||||
spending_proposal_features:
|
||||
|
||||
@@ -61,6 +61,8 @@ Rails.application.routes.draw do
|
||||
end
|
||||
end
|
||||
|
||||
resources :proposal_ballots, only: [:index]
|
||||
|
||||
resources :comments, only: [:create, :show], shallow: true do
|
||||
member do
|
||||
post :vote
|
||||
|
||||
@@ -13,6 +13,7 @@ Setting.create(key: 'max_votes_for_debate_edit', value: '1000')
|
||||
Setting.create(key: 'max_votes_for_proposal_edit', value: '1000')
|
||||
Setting.create(key: 'proposal_code_prefix', value: 'MAD')
|
||||
Setting.create(key: 'votes_for_proposal_success', value: '100')
|
||||
Setting.create(key: 'months_to_archive_proposals', value: '12')
|
||||
Setting.create(key: 'comments_body_max_length', value: '1000')
|
||||
|
||||
Setting.create(key: 'twitter_handle', value: '@consul_dev')
|
||||
@@ -149,7 +150,7 @@ tags = Faker::Lorem.words(25)
|
||||
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
|
||||
proposal = Proposal.create!(author: author,
|
||||
title: Faker::Lorem.sentence(3).truncate(60),
|
||||
question: Faker::Lorem.sentence(3),
|
||||
question: Faker::Lorem.sentence(3) + "?",
|
||||
summary: Faker::Lorem.sentence(3),
|
||||
responsible_name: Faker::Name.name,
|
||||
external_url: Faker::Internet.url,
|
||||
@@ -161,6 +162,27 @@ tags = Faker::Lorem.words(25)
|
||||
puts " #{proposal.title}"
|
||||
end
|
||||
|
||||
puts "Creating Archived Proposals"
|
||||
|
||||
tags = Faker::Lorem.words(25)
|
||||
(1..5).each do |i|
|
||||
author = User.reorder("RANDOM()").first
|
||||
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
|
||||
proposal = Proposal.create!(author: author,
|
||||
title: Faker::Lorem.sentence(3).truncate(60),
|
||||
question: Faker::Lorem.sentence(3) + "?",
|
||||
summary: Faker::Lorem.sentence(3),
|
||||
responsible_name: Faker::Name.name,
|
||||
external_url: Faker::Internet.url,
|
||||
description: description,
|
||||
created_at: rand((Time.now - 1.week) .. Time.now),
|
||||
tag_list: tags.sample(3).join(','),
|
||||
geozone: Geozone.reorder("RANDOM()").first,
|
||||
terms_of_service: "1",
|
||||
created_at: Setting["months_to_archive_proposals"].to_i.months.ago)
|
||||
puts " #{proposal.title}"
|
||||
end
|
||||
|
||||
|
||||
tags = ActsAsTaggableOn::Tag.where(kind: 'category')
|
||||
(1..30).each do |i|
|
||||
@@ -168,7 +190,7 @@ tags = ActsAsTaggableOn::Tag.where(kind: 'category')
|
||||
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
|
||||
proposal = Proposal.create!(author: author,
|
||||
title: Faker::Lorem.sentence(3).truncate(60),
|
||||
question: Faker::Lorem.sentence(3),
|
||||
question: Faker::Lorem.sentence(3) + "?",
|
||||
summary: Faker::Lorem.sentence(3),
|
||||
responsible_name: Faker::Name.name,
|
||||
external_url: Faker::Internet.url,
|
||||
|
||||
6
db/migrate/20160901104320_add_password_expired.rb
Normal file
6
db/migrate/20160901104320_add_password_expired.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
class AddPasswordExpired < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :users, :password_changed_at, :datetime
|
||||
add_index :users, :password_changed_at
|
||||
end
|
||||
end
|
||||
@@ -491,12 +491,14 @@ ActiveRecord::Schema.define(version: 20160928113143) do
|
||||
t.boolean "email_digest", default: true
|
||||
t.boolean "email_on_direct_message", default: true
|
||||
t.boolean "official_position_badge", default: false
|
||||
t.datetime "password_changed_at"
|
||||
end
|
||||
|
||||
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
|
||||
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
|
||||
add_index "users", ["geozone_id"], name: "index_users_on_geozone_id", using: :btree
|
||||
add_index "users", ["hidden_at"], name: "index_users_on_hidden_at", using: :btree
|
||||
add_index "users", ["password_changed_at"], name: "index_users_on_password_changed_at", using: :btree
|
||||
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
|
||||
add_index "users", ["username"], name: "index_users_on_username", using: :btree
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ Setting["proposal_code_prefix"] = 'MAD'
|
||||
# Number of votes needed for proposal success
|
||||
Setting["votes_for_proposal_success"] = 53726
|
||||
|
||||
# Months to archive proposals
|
||||
Setting["months_to_archive_proposals"] = 12
|
||||
|
||||
# Users with this email domain will automatically be marked as level 1 officials
|
||||
# Emails under the domain's subdomains will also be included
|
||||
Setting["email_domain_for_officials"] = ''
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
## Linux
|
||||
|
||||
See [here](dev_test_setup_linux.md)
|
||||
|
||||
## Mac OS X
|
||||
|
||||
See [here](dev_test_setup_osx.md)
|
||||
|
||||
126
doc/en/dev_test_setup_linux.md
Normal file
126
doc/en/dev_test_setup_linux.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Configuration for development and test environments (GNU/Linux)
|
||||
|
||||
## Git
|
||||
|
||||
Git is officially maintained in Debian/Ubuntu:
|
||||
|
||||
```
|
||||
sudo apt-get install git
|
||||
```
|
||||
|
||||
## Ruby
|
||||
|
||||
Ruby versions packaged in official repositories are not suitable to work with consul (at least Debian 7 and 8), so we'll have to install it manually.
|
||||
|
||||
The preferred method is via rvm:
|
||||
|
||||
(only the multi user option installs all dependencies automatically, as we use 'sudo'.)
|
||||
|
||||
###as local user:
|
||||
|
||||
```
|
||||
curl -L https://get.rvm.io | bash -s stable
|
||||
```
|
||||
###for all system users
|
||||
|
||||
```
|
||||
curl -L https://get.rvm.io | sudo bash -s stable
|
||||
```
|
||||
|
||||
and then add your user to rvm group
|
||||
|
||||
```
|
||||
sudo usermod -a -G rvm <user>
|
||||
```
|
||||
|
||||
and finally, add rvm script source to user's bash (~/.bashrc) (this step it's only necessary if you still can't execute rvm command)
|
||||
|
||||
```
|
||||
[[ -s /usr/local/rvm/scripts/rvm ]] && source /usr/local/rvm/scripts/rvm
|
||||
```
|
||||
|
||||
with all this, you are suppose to be able to install a ruby version from rvm, as for example version 2.3.0:
|
||||
|
||||
```
|
||||
sudo rvm install 2.3.0
|
||||
```
|
||||
|
||||
## Bundler
|
||||
|
||||
with
|
||||
|
||||
```
|
||||
gem install bundler
|
||||
```
|
||||
|
||||
or there is more methods [here](https://rvm.io/integration/bundler) that should be better as:
|
||||
|
||||
```
|
||||
gem install rubygems-bundler
|
||||
```
|
||||
|
||||
## PostgreSQL (>=9.4)
|
||||
|
||||
PostgreSQL version 9.4 is not official in debian 7 (wheezy), in 8 it seems to be officially maintained.
|
||||
|
||||
So you have to add a repository, the official postgresql works fine.
|
||||
|
||||
Add the repository to apt, for example creating file */etc/apt/sources.list.d/pgdg.list* with:
|
||||
|
||||
```
|
||||
deb http://apt.postgresql.org/pub/repos/apt/ wheezy-pgdg main
|
||||
```
|
||||
|
||||
afterwards you'll have to download the key, and install it, by:
|
||||
|
||||
```
|
||||
wget https://www.postgresql.org/media/keys/ACCC4CF8.asc
|
||||
apt-key add ACCC4CF8.asc
|
||||
```
|
||||
|
||||
and install postgresql
|
||||
|
||||
```
|
||||
apt-get update
|
||||
apt-get install postgresql-9.4
|
||||
```
|
||||
|
||||
## Ghostscript
|
||||
|
||||
```
|
||||
apt-get install ghostscript
|
||||
```
|
||||
|
||||
## Cloning the repository
|
||||
|
||||
Now, with all the dependencies installed, clone the Consul repository:
|
||||
|
||||
```
|
||||
git clone https://github.com/consul/consul.git
|
||||
cd consul
|
||||
bundle install
|
||||
cp config/database.yml.example config/database.yml
|
||||
cp config/secrets.yml.example config/secrets.yml
|
||||
```
|
||||
Perhaps it's needed to create a superuser rol with password in postgresql, and write it in */config/database.yml* 'user:' and 'password:' fields.
|
||||
|
||||
Also, it seems that postgresql use as default an unix socket for localhost communications. If we encounter problems creating database (connection problems) we can change in */config/database.yml* the line:
|
||||
|
||||
```
|
||||
host: localhost
|
||||
```
|
||||
|
||||
for:
|
||||
|
||||
```
|
||||
host: /var/run/postgresql
|
||||
```
|
||||
|
||||
After this:
|
||||
|
||||
```
|
||||
rake db:create
|
||||
rake db:setup
|
||||
rake db:dev_seed
|
||||
RAILS_ENV=test bin/rake db:setup
|
||||
```
|
||||
@@ -76,4 +76,12 @@ namespace :users do
|
||||
task remove_erased_identities: :environment do
|
||||
Identity.joins(:user).where('users.erased_at IS NOT NULL').destroy_all
|
||||
end
|
||||
|
||||
desc "Update password changed at for existing users"
|
||||
task update_password_changed_at: :environment do
|
||||
User.all.each do |user|
|
||||
user.update(password_changed_at: user.created_at)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background: #065687 url('errors_bg.jpg');
|
||||
background: #065687 url('/errors_bg.jpg');
|
||||
color: #2E2F30;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background: #065687 url('errors_bg.jpg');
|
||||
background: #065687 url('/errors_bg.jpg');
|
||||
color: #2E2F30;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background: #065687 url('errors_bg.jpg');
|
||||
background: #065687 url('/errors_bg.jpg');
|
||||
color: #2E2F30;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
|
||||
22
spec/customization_engine_spec.rb
Normal file
22
spec/customization_engine_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
require 'rails_helper'
|
||||
|
||||
# This module tests functionality related with custom application files
|
||||
# TODO test models, controllers, etc...
|
||||
|
||||
describe 'CustomizationEngine' do
|
||||
|
||||
let(:test_key) { I18n.t('account.show.change_credentials_link') }
|
||||
|
||||
it "should load custom and override original locales" do
|
||||
I18n.load_path += Dir[Rails.root.join('spec', 'support', 'locales', 'custom', '*.{rb,yml}')]
|
||||
I18n.reload!
|
||||
expect(test_key).to eq 'Overriden string with custom locales'
|
||||
end
|
||||
|
||||
it "should not override original locales" do
|
||||
I18n.load_path.delete_if {|item| item =~ /spec\/support\/locales\/custom/ }
|
||||
I18n.load_path += Dir[Rails.root.join('spec', 'support', 'locales', '**', '*.{rb,yml}')]
|
||||
I18n.reload!
|
||||
expect(test_key).to eq 'Not overriden string with custom locales'
|
||||
end
|
||||
end
|
||||
@@ -163,6 +163,10 @@ FactoryGirl.define do
|
||||
end
|
||||
end
|
||||
|
||||
trait :archived do
|
||||
created_at 25.months.ago
|
||||
end
|
||||
|
||||
trait :with_hot_score do
|
||||
before(:save) { |d| d.calculate_hot_score }
|
||||
end
|
||||
|
||||
@@ -50,7 +50,7 @@ feature 'Official positions' do
|
||||
@proposal1 = create(:proposal, author: @user1)
|
||||
@proposal2 = create(:proposal, author: @user2)
|
||||
|
||||
featured_proposals = 3.times { create(:proposal) }
|
||||
create_featured_proposals
|
||||
end
|
||||
|
||||
scenario "Index" do
|
||||
|
||||
57
spec/features/proposal_ballots_spec.rb
Normal file
57
spec/features/proposal_ballots_spec.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
# coding: utf-8
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Proposal ballots' do
|
||||
|
||||
scenario 'Banner shows in proposal index' do
|
||||
create_featured_proposals
|
||||
|
||||
visit proposals_path
|
||||
expect(page).to_not have_css("#next-voting")
|
||||
expect(page).to have_css("#featured-proposals")
|
||||
|
||||
create_successfull_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_css("#next-voting")
|
||||
expect(page).to_not have_css("#featured-proposals")
|
||||
end
|
||||
|
||||
scenario 'Successfull proposals do not show support buttons in index' do
|
||||
successfull_proposals = create_successfull_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
successfull_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to_not have_css(".supports")
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Successfull proposals do not show support buttons in show' do
|
||||
successfull_proposals = create_successfull_proposals
|
||||
|
||||
successfull_proposals.each do |proposal|
|
||||
visit proposal_path(proposal)
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to_not have_css(".supports")
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Successfull proposals are listed in the proposal ballots index' do
|
||||
successfull_proposals = create_successfull_proposals
|
||||
|
||||
visit proposal_ballots_path
|
||||
|
||||
successfull_proposals.each do |proposal|
|
||||
expect(page).to have_content(proposal.title)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,48 +3,50 @@ require 'rails_helper'
|
||||
|
||||
feature 'Proposals' do
|
||||
|
||||
scenario 'Index' do
|
||||
featured_proposals = create_featured_proposals
|
||||
proposals = [create(:proposal), create(:proposal), create(:proposal)]
|
||||
context 'Index' do
|
||||
scenario 'Lists featured and regular proposals' do
|
||||
featured_proposals = create_featured_proposals
|
||||
proposals = [create(:proposal), create(:proposal), create(:proposal)]
|
||||
|
||||
visit proposals_path
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal-featured', count: 3)
|
||||
featured_proposals.each do |featured_proposal|
|
||||
within('#featured-proposals') do
|
||||
expect(page).to have_content featured_proposal.title
|
||||
expect(page).to have_css("a[href='#{proposal_path(featured_proposal)}']")
|
||||
expect(page).to have_selector('#proposals .proposal-featured', count: 3)
|
||||
featured_proposals.each do |featured_proposal|
|
||||
within('#featured-proposals') do
|
||||
expect(page).to have_content featured_proposal.title
|
||||
expect(page).to have_css("a[href='#{proposal_path(featured_proposal)}']")
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: 3)
|
||||
proposals.each do |proposal|
|
||||
within('#proposals') do
|
||||
expect(page).to have_content proposal.title
|
||||
expect(page).to have_css("a[href='#{proposal_path(proposal)}']", text: proposal.title)
|
||||
expect(page).to have_css("a[href='#{proposal_path(proposal)}']", text: proposal.summary)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: 3)
|
||||
proposals.each do |proposal|
|
||||
within('#proposals') do
|
||||
expect(page).to have_content proposal.title
|
||||
expect(page).to have_css("a[href='#{proposal_path(proposal)}']", text: proposal.title)
|
||||
expect(page).to have_css("a[href='#{proposal_path(proposal)}']", text: proposal.summary)
|
||||
scenario 'Pagination' do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 5).times { create(:proposal) }
|
||||
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: per_page)
|
||||
|
||||
within("ul.pagination") do
|
||||
expect(page).to have_content("1")
|
||||
expect(page).to have_content("2")
|
||||
expect(page).to_not have_content("3")
|
||||
click_link "Next", exact: false
|
||||
end
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: 2)
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Paginated Index' do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 5).times { create(:proposal) }
|
||||
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: per_page)
|
||||
|
||||
within("ul.pagination") do
|
||||
expect(page).to have_content("1")
|
||||
expect(page).to have_content("2")
|
||||
expect(page).to_not have_content("3")
|
||||
click_link "Next", exact: false
|
||||
end
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: 2)
|
||||
end
|
||||
|
||||
scenario 'Show' do
|
||||
proposal = create(:proposal)
|
||||
|
||||
@@ -676,6 +678,110 @@ feature 'Proposals' do
|
||||
end
|
||||
end
|
||||
|
||||
feature 'Archived proposals' do
|
||||
|
||||
scenario 'show on archived tab' do
|
||||
create_featured_proposals
|
||||
archived_proposals = create_archived_proposals
|
||||
|
||||
visit proposals_path
|
||||
click_link 'Archived'
|
||||
|
||||
within("#proposals-list") do
|
||||
archived_proposals.each do |proposal|
|
||||
expect(page).to have_content(proposal.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'do not show in other index tabs' do
|
||||
create_featured_proposals
|
||||
archived_proposal = create(:proposal, :archived)
|
||||
|
||||
visit proposals_path
|
||||
|
||||
within("#proposals-list") do
|
||||
expect(page).to_not have_content archived_proposal.title
|
||||
end
|
||||
|
||||
orders = %w{hot_score confidence_score created_at relevance}
|
||||
orders.each do |order|
|
||||
visit proposals_path(order: order)
|
||||
|
||||
within("#proposals-list") do
|
||||
expect(page).to_not have_content archived_proposal.title
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'do not show support buttons in index' do
|
||||
create_featured_proposals
|
||||
archived_proposals = create_archived_proposals
|
||||
|
||||
visit proposals_path(order: 'archival_date')
|
||||
|
||||
within("#proposals-list") do
|
||||
archived_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to_not have_css(".supports")
|
||||
expect(page).to have_content "This proposal has been archived and can't collect supports"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'do not show support buttons in show' do
|
||||
archived_proposal = create(:proposal, :archived)
|
||||
|
||||
visit proposal_path(archived_proposal)
|
||||
expect(page).to_not have_css(".supports")
|
||||
expect(page).to have_content "This proposal has been archived and can't collect supports"
|
||||
end
|
||||
|
||||
scenario 'do not show in featured proposals section' do
|
||||
featured_proposal = create(:proposal, :with_confidence_score, cached_votes_up: 100)
|
||||
archived_proposal = create(:proposal, :archived, :with_confidence_score, cached_votes_up: 10000)
|
||||
|
||||
visit proposals_path
|
||||
|
||||
within("#featured-proposals") do
|
||||
expect(page).to have_content(featured_proposal.title)
|
||||
expect(page).to_not have_content(archived_proposal.title)
|
||||
end
|
||||
within("#proposals-list") do
|
||||
expect(page).to_not have_content(featured_proposal.title)
|
||||
expect(page).to_not have_content(archived_proposal.title)
|
||||
end
|
||||
|
||||
click_link "Archived"
|
||||
|
||||
within("#featured-proposals") do
|
||||
expect(page).to have_content(featured_proposal.title)
|
||||
expect(page).to_not have_content(archived_proposal.title)
|
||||
end
|
||||
within("#proposals-list") do
|
||||
expect(page).to_not have_content(featured_proposal.title)
|
||||
expect(page).to have_content(archived_proposal.title)
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Order by votes" do
|
||||
create(:proposal, :archived, title: "Least voted").update_column(:confidence_score, 10)
|
||||
create(:proposal, :archived, title: "Most voted").update_column(:confidence_score, 50)
|
||||
create(:proposal, :archived, title: "Some votes").update_column(:confidence_score, 25)
|
||||
|
||||
visit proposals_path
|
||||
click_link 'Archived'
|
||||
|
||||
within("#proposals-list") do
|
||||
expect(all(".proposal")[0].text).to match "Most voted"
|
||||
expect(all(".proposal")[1].text).to match "Some votes"
|
||||
expect(all(".proposal")[2].text).to match "Least voted"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Search" do
|
||||
|
||||
context "Basic search" do
|
||||
|
||||
@@ -285,4 +285,59 @@ feature 'Users' do
|
||||
|
||||
expect(page).to have_content "Your password has been changed successfully."
|
||||
end
|
||||
|
||||
scenario 'Sign in, admin with password expired' do
|
||||
user = create(:user, password_changed_at: Time.now - 1.year)
|
||||
admin = create(:administrator, user: user)
|
||||
|
||||
login_as(admin.user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_content "Your password is expired"
|
||||
|
||||
fill_in 'user_current_password', with: 'judgmentday'
|
||||
fill_in 'user_password', with: '123456789'
|
||||
fill_in 'user_password_confirmation', with: '123456789'
|
||||
|
||||
click_button 'Change your password'
|
||||
|
||||
expect(page).to have_content "Password successfully updated"
|
||||
end
|
||||
|
||||
scenario 'Sign in, admin without password expired' do
|
||||
user = create(:user, password_changed_at: Time.now - 360.days)
|
||||
admin = create(:administrator, user: user)
|
||||
|
||||
login_as(admin.user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_content "Your password is expired"
|
||||
end
|
||||
|
||||
scenario 'Sign in, user with password expired' do
|
||||
user = create(:user, password_changed_at: Time.now - 1.year)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to_not have_content "Your password is expired"
|
||||
end
|
||||
|
||||
scenario 'Admin with password expired trying to use same password' do
|
||||
user = create(:user, password_changed_at: Time.now - 1.year, password: '123456789')
|
||||
admin = create(:administrator, user: user)
|
||||
|
||||
login_as(admin.user)
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_content "Your password is expired"
|
||||
|
||||
fill_in 'user_current_password', with: 'judgmentday'
|
||||
fill_in 'user_password', with: '123456789'
|
||||
fill_in 'user_password_confirmation', with: '123456789'
|
||||
click_button 'Change your password'
|
||||
|
||||
expect(page).to have_content "must be different than the current password."
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -204,6 +204,13 @@ describe Proposal do
|
||||
expect {proposal.register_vote(user, 'yes')}.to change{proposal.reload.votes_for.size}.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
it "should not register vote for archived proposals" do
|
||||
user = create(:user, verified_at: Time.now)
|
||||
archived_proposal = create(:proposal, :archived)
|
||||
|
||||
expect {archived_proposal.register_vote(user, 'yes')}.to change{proposal.reload.votes_for.size}.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cached_votes_up' do
|
||||
@@ -811,4 +818,30 @@ describe Proposal do
|
||||
end
|
||||
end
|
||||
|
||||
describe "archived" do
|
||||
before(:each) do
|
||||
@new_proposal = create(:proposal)
|
||||
@archived_proposal = create(:proposal, :archived)
|
||||
end
|
||||
|
||||
it "archived? is true only for proposals created more than n (configured months) ago" do
|
||||
expect(@new_proposal.archived?).to eq false
|
||||
expect(@archived_proposal.archived?).to eq true
|
||||
end
|
||||
|
||||
it "scope archived" do
|
||||
archived = Proposal.archived
|
||||
|
||||
expect(archived.size).to eq(1)
|
||||
expect(archived.first).to eq(@archived_proposal)
|
||||
end
|
||||
|
||||
it "scope archived" do
|
||||
not_archived = Proposal.not_archived
|
||||
|
||||
expect(not_archived.size).to eq(1)
|
||||
expect(not_archived.first).to eq(@new_proposal)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -192,6 +192,16 @@ module CommonActions
|
||||
create(:debate, :with_confidence_score, cached_votes_up: 80)]
|
||||
end
|
||||
|
||||
def create_successfull_proposals
|
||||
[create(:proposal, title: "Winter is coming", question: "Do you speak it?", cached_votes_up: Proposal.votes_needed_for_success + 100),
|
||||
create(:proposal, title: "Fire and blood", question: "You talking to me?", cached_votes_up: Proposal.votes_needed_for_success + 1)]
|
||||
end
|
||||
|
||||
def create_archived_proposals
|
||||
[create(:proposal, title: "This is an expired proposal", created_at: Setting["months_to_archive_proposals"].to_i.months.ago),
|
||||
create(:proposal, title: "This is an oldest expired proposal", created_at: (Setting["months_to_archive_proposals"].to_i + 2).months.ago)]
|
||||
end
|
||||
|
||||
def tag_names(tag_cloud)
|
||||
tag_cloud.tags.map(&:name)
|
||||
end
|
||||
|
||||
5
spec/support/locales/custom/en.yml
Normal file
5
spec/support/locales/custom/en.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
en:
|
||||
account:
|
||||
show:
|
||||
change_credentials_link: Overriden string with custom locales
|
||||
5
spec/support/locales/en.yml
Normal file
5
spec/support/locales/en.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
en:
|
||||
account:
|
||||
show:
|
||||
change_credentials_link: Not overriden string with custom locales
|
||||
Reference in New Issue
Block a user