diff --git a/.gitignore b/.gitignore
index eb917c637..5cc519787 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,5 +19,6 @@
/spec/examples.txt
/config/database.yml
/config/secrets.yml
+/config/deploy-secrets.yml
/coverage
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e46777e3d..af11c122b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -43,3 +43,5 @@ Cuando quieras resolver una incidencia mediante código:
* Lo que se esperaba que pasara
* Lo que ha pasado
* También es buena idea que incluyas tu sistema operativo, navegador, versión de navegador y plugins instalados.
+
+¡Gracias! :heart: :heart: :heart:
diff --git a/CONTRIBUTING_EN.md b/CONTRIBUTING_EN.md
new file mode 100644
index 000000000..26e08fc11
--- /dev/null
+++ b/CONTRIBUTING_EN.md
@@ -0,0 +1,46 @@
+## Team members
+
+* Raimond Garcia [github](https://github.com/voodoorai2000) | [twitter](https://twitter.com/voodoorai2000)
+* Juanjo Bazán [github](https://github.com/xuanxu) | [twitter](https://twitter.com/xuanxu)
+* Enrique García Cota [github](https://github.com/kikito) | [twitter](https://twitter.com/otikik)
+* Alberto Garcia Cabeza [github](https://github.com/decabeza) | [twitter](https://twitter.com/decabeza)
+
+## Report an issue
+
+The prefered way to report any bug is [opening an issue in the project's Github repo](https://github.com/AyuntamientoMadrid/participacion/issues/new).
+
+For more informal communication, contact team members via twitter
+
+## Resolve an issue
+
+Admins tag issues using two label related with collaboration availability:
+
+* `PRs-welcome`: [issues labeled with PRs-welcome](https://github.com/AyuntamientoMadrid/participacion/labels/PRs-welcome) are well defined features ready to be implemented by whoever wants to do it.
+
+* `Not-ready`: with this label admins mark features or changes that are not well defined yet or subject to an internal decision. Is not a good idea to start implementation of these isuues.
+
+If you want to contribute code to solve an issue:
+
+* Add a comment to tell everyone you are working on the issue.
+* If an issue has someone assigned it means that person is already working on it.
+* Fork the project.
+* Create a topic branch based on master.
+* Commit there your code to solve the issue.
+* Make sure all test are passing (and add specs to test any new feature if needed).
+* Open a *pull request* to the main repository describing what issue you are addressing.
+
+## Other ways of contributing without coding
+
+* If you think there's a feature missing, or find a bug, create an issue (make sure it has not already been reported).
+* You can also help promoting the project talking about it in your social networks.
+
+## How to report an issue
+
+* Try to use a descriptive and to-the-point title
+* Is a good idea to include some of there sections:
+ * Steps to reproduce the bug
+ * Expected behaviour/response
+ * Actual response
+* Sometimes it is also helpful if you mention your operating system, browser version and installed plugins.
+
+Thanks! :heart: :heart: :heart:
\ No newline at end of file
diff --git a/Capfile b/Capfile
new file mode 100644
index 000000000..b565fae23
--- /dev/null
+++ b/Capfile
@@ -0,0 +1,14 @@
+# Load DSL and set up stages
+require 'capistrano/setup'
+
+# Include default deployment tasks
+require 'capistrano/deploy'
+
+require 'capistrano/rvm'
+require 'capistrano/bundler'
+require 'capistrano/rails/assets'
+require 'capistrano/rails/migrations'
+require 'capistrano/passenger'
+
+# Load custom tasks from `lib/capistrano/tasks` if you have any defined
+Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
diff --git a/Gemfile b/Gemfile
index 00e2a98eb..7340871bb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,5 @@
source 'https://rubygems.org'
-
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.3'
# Use PostgreSQL
@@ -26,11 +25,6 @@ gem 'devise'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'acts_as_commentable_with_threading'
-# Use Unicorn as the app server
-# gem 'unicorn'
-
-# Use Capistrano for deployment
-# gem 'capistrano-rails', group: :development
gem 'acts-as-taggable-on'
gem "responders"
gem 'foundation-rails'
@@ -53,6 +47,11 @@ group :development, :test do
gem 'quiet_assets'
gem 'letter_opener_web', '~> 1.2.0'
gem 'i18n-tasks'
+ gem 'capistrano', '3.4.0', require: false
+ gem "capistrano-bundler", '1.1.4', require: false
+ gem "capistrano-rails", '1.1.3', require: false
+ gem "capistrano-rvm", require: false
+ gem "capistrano-passenger", require: false
end
group :test do
@@ -61,3 +60,7 @@ group :test do
gem 'coveralls', require: false
end
+group :test do
+ gem 'email_spec'
+end
+
diff --git a/Gemfile.lock b/Gemfile.lock
index 67f4a7616..cf6709f66 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -54,6 +54,21 @@ GEM
byebug (5.0.0)
columnize (= 0.9.0)
cancancan (1.12.0)
+ capistrano (3.4.0)
+ i18n
+ rake (>= 10.0.0)
+ sshkit (~> 1.3)
+ capistrano-bundler (1.1.4)
+ capistrano (~> 3.1)
+ sshkit (~> 1.2)
+ capistrano-passenger (0.1.1)
+ capistrano (~> 3.0)
+ capistrano-rails (1.1.3)
+ capistrano (~> 3.1)
+ capistrano-bundler (~> 1.1)
+ capistrano-rvm (0.1.2)
+ capistrano (~> 3.0)
+ sshkit (~> 1.2)
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@@ -75,6 +90,7 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.9.1.1)
+ colorize (0.7.7)
columnize (0.9.0)
coveralls (0.8.2)
json (~> 1.8)
@@ -99,6 +115,9 @@ GEM
json
thread
thread_safe
+ email_spec (1.6.0)
+ launchy (~> 2.1)
+ mail (~> 2.2)
erubis (2.7.0)
execjs (2.5.2)
factory_girl (4.5.0)
@@ -146,6 +165,9 @@ GEM
mini_portile (0.6.2)
minitest (5.7.0)
multi_json (1.11.2)
+ net-scp (1.2.1)
+ net-ssh (>= 2.6.5)
+ net-ssh (2.9.2)
netrc (0.10.3)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
@@ -233,6 +255,10 @@ GEM
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
+ sshkit (1.7.1)
+ colorize (>= 0.7.0)
+ net-scp (>= 1.1.2)
+ net-ssh (>= 2.8.0)
term-ansicolor (1.3.2)
tins (~> 1.0)
terminal-table (1.5.2)
@@ -273,12 +299,18 @@ DEPENDENCIES
acts_as_votable
byebug
cancancan
+ capistrano (= 3.4.0)
+ capistrano-bundler (= 1.1.4)
+ capistrano-passenger
+ capistrano-rails (= 1.1.3)
+ capistrano-rvm
capybara
ckeditor
coffee-rails (~> 4.1.0)
coveralls
database_cleaner
devise
+ email_spec
factory_girl_rails
foundation-rails
i18n-tasks
diff --git a/README.md b/README.md
index 1df4987c8..66c1853dc 100644
--- a/README.md
+++ b/README.md
@@ -27,8 +27,8 @@ cd participacion
bundle install
cp config/database.yml.example config/database.yml
cp config/secrets.yml.example config/secrets.yml
-bundle exec bin/rake db:create db:schema:load
-RAILS_ENV=test bundle exec rake db:create db:schema:load
+bundle exec bin/rake db:setup
+RAILS_ENV=test bundle exec rake db:setup
```
Para ejecutar la aplicación en local:
@@ -47,4 +47,4 @@ El código de este proyecto está publicado bajo la licencia MIT (ver MIT-licens
## Contribuciones
-Ver fichero CONTRIBUTING.md
+Ver fichero [CONTRIBUTING.md](CONTRIBUTING.md)
diff --git a/README_EN.md b/README_EN.md
new file mode 100644
index 000000000..b1b1521ff
--- /dev/null
+++ b/README_EN.md
@@ -0,0 +1,51 @@
+# Ayuntamiento de Madrid (Madrid city's government) eParticipation application
+
+[](https://travis-ci.org/AyuntamientoMadrid/participacion)
+[](https://codeclimate.com/github/AyuntamientoMadrid/participacion)
+[](https://gemnasium.com/AyuntamientoMadrid/participacion)
+[](https://coveralls.io/github/AyuntamientoMadrid/participacion?branch=master)
+
+This is the opensource code repository of Madrid City government eParticipation website
+
+## Current state
+
+Development started on [2015 July 15th](https://github.com/AyuntamientoMadrid/participacion/commit/8db36308379accd44b5de4f680a54c41a0cc6fc6)
+
+The project is in its early stages. Features currently present in the code (and their names) are subject to change.
+
+## Tech stack
+
+The application backend is written in the [Ruby language](https://www.ruby-lang.org/) using the [Ruby on Rails](http://rubyonrails.org/) framework.
+
+Frontend tools used include [SCSS](http://sass-lang.com/) over [Foundation](http://foundation.zurb.com/) for the styles.
+
+## Configuration for development and test environments
+
+Prerequisites: install git, Ruby 2.2.2, bundler gem and PostgreSQL.
+
+```
+cd participacion
+bundle install
+cp config/database.yml.example config/database.yml
+cp config/secrets.yml.example config/secrets.yml
+bundle exec bin/rake db:setup
+RAILS_ENV=test bundle exec rake db:setup
+```
+
+Run the app locally:
+```
+bundle exec bin/rails s
+```
+
+Run the tests with:
+```
+bundle exec bin/rspec
+```
+
+## Licence
+
+Code published under MIT license (see [MIT-license.md](MIT-license.md))
+
+## Contributions
+
+See [CONTRIBUTING_EN.md](CONTRIBUTING_EN.md)
diff --git a/app/assets/images/home_header_bg.jpg b/app/assets/images/home_header_bg.jpg
index f264aa06f..3f5065f9b 100644
Binary files a/app/assets/images/home_header_bg.jpg and b/app/assets/images/home_header_bg.jpg differ
diff --git a/app/assets/stylesheets/debates.scss b/app/assets/stylesheets/debates.scss
index d8fabd59d..c74ef5057 100644
--- a/app/assets/stylesheets/debates.scss
+++ b/app/assets/stylesheets/debates.scss
@@ -96,7 +96,49 @@ header {
.button {
color: white;
font-family: inherit;
- margin-top: $line-height*2;
+ margin-top: $line-height;
+ }
+
+ .home-page {
+ .button {
+ color: white;
+ font-family: inherit;
+ margin-top: $line-height*2;
+ }
+ }
+
+ .selected {
+ position: relative;
+
+ &:before {
+ top: -14px;
+ left: 50%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ border-top-color: #fff;
+ border-width: 8px;
+ margin-left: -8px;
+ }
+ }
+
+ .language {
+ float: none;
+ text-align: center;
+
+ @media (min-width: 480px) {
+ float: left;
+ }
+ }
+
+ .external-links {
+ @extend .language;
+
+ @media (min-width: 480px) {
+ float: right;
+ }
}
}
@@ -105,13 +147,13 @@ header {
}
.top-bar {
- background: white;
- color: $header-color;
+ background: rgba(0,0,0,.5);
+ color: white; //$header-color;
height: $line-height*4;
max-width: 1170px !important;
.name a {
- color: black;
+ color: white;
font-family: 'Lato';
font-size: rem-calc(36);
font-weight: lighter;
@@ -119,7 +161,7 @@ header {
padding-left: 0;
span {
- color: $brand;
+ // color: $brand;
font-size: rem-calc(24);
font-weight: normal;
}
@@ -131,14 +173,29 @@ header {
}
.top-bar-section {
+ margin-right: $line-height;
+
+ ul li > a {
+ font-size: rem-calc(14);
+ }
+
+ ul li, ul li:hover:not(.has-form) > a {
+ background: none;
+ }
li:not(.has-form) a:not(.button) {
- background: white;
- color: $brand;
+ background: none;
+ color: white;
line-height: $line-height*4;
+
+ &:hover {
+ background: none;
+ color: $link-hover;
+ }
}
li.active:not(.has-form) a:not(.button) {
+ background: none;
height: $line-height*4;
line-height: $line-height*4;
}
@@ -147,9 +204,13 @@ header {
.top-links {
color: white;
font-size: rem-calc(14);
- height: $line-height*2;
+ height: $line-height*3;
padding: $line-height/2 0;
+ @media (min-width: 480px) {
+ height: $line-height*2;
+ }
+
a {
color: white;
}
@@ -179,7 +240,7 @@ header {
.icon-like {
background: white;
- border: 2px solid white;
+ border: 2px solid $votes-border;
border-radius: rem-calc(3);
color: $votes-neutral;
display: inline-block;
@@ -187,10 +248,10 @@ header {
line-height: rem-calc(30);
padding: rem-calc(3) rem-calc(6);
position: relative;
- //when active => color: $votes-like;
&:hover {
background: $votes-like;
+ border-color: white;
color: white;
cursor: pointer;
}
@@ -202,7 +263,7 @@ header {
.icon-unlike {
background: white;
- border: 2px solid white;
+ border: 2px solid $votes-border;
border-radius: rem-calc(3);
color: $votes-neutral;
display: inline-block;
@@ -210,10 +271,10 @@ header {
line-height: rem-calc(30);
padding: rem-calc(3) rem-calc(6);
position: relative;
- //when active => color: $votes-unlike;
&:hover {
background: $votes-unlike;
+ border-color: white;
color: white;
cursor: pointer;
}
diff --git a/app/assets/stylesheets/variables.scss b/app/assets/stylesheets/variables.scss
index f9607af9c..37123d553 100644
--- a/app/assets/stylesheets/variables.scss
+++ b/app/assets/stylesheets/variables.scss
@@ -26,7 +26,8 @@ $comments-info: #A5B2B9;
$comments-text: #3F4549;
$header-color: #292B33;
-$link: #0077B9;
+$link: #2895F1;
+$link-hover: #2178BF;
$tags-bg: #FAFAFA;
$tags-border: #F0F0F0;
@@ -37,8 +38,8 @@ $text-medium: #999999;
$text-light: #A3A6AD;
$votes: #31708f;
-$votes-background: #0081B3;
-$votes-border: #005b80;
+$votes-background: #26AEEE;//#0081B3;
+$votes-border: #1F94CB;//#005b80;
$votes-like: #7BD2A8;
$votes-like-act: #5D9E7F;
$votes-neutral: #CCCCCC;
diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb
index 494068476..e9b5b6c99 100644
--- a/app/controllers/account_controller.rb
+++ b/app/controllers/account_controller.rb
@@ -17,7 +17,7 @@ class AccountController < ApplicationController
end
def account_params
- params.require(:account).permit(:first_name, :last_name, :nickname, :use_nickname)
+ params.require(:account).permit(:first_name, :last_name, :nickname, :use_nickname, :email_on_debate_comment, :email_on_comment_reply)
end
end
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 409bb7c9b..bbad3ca3b 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -7,6 +7,10 @@ class CommentsController < ApplicationController
@comment = Comment.build(@debate, current_user, params[:comment][:body])
@comment.save!
@comment.move_to_child_of(@parent) if reply?
+
+ Mailer.comment(@comment).deliver_now if email_on_debate_comment?
+ Mailer.reply(@comment).deliver_now if email_on_comment_reply?
+
respond_with @comment
end
@@ -32,4 +36,12 @@ class CommentsController < ApplicationController
def reply?
@parent.class == Comment
end
+
+ def email_on_debate_comment?
+ @comment.debate.author.email_on_debate_comment?
+ end
+
+ def email_on_comment_reply?
+ reply? && @parent.author.email_on_comment_reply?
+ end
end
\ No newline at end of file
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644
index 000000000..e5d793e1e
--- /dev/null
+++ b/app/mailers/application_mailer.rb
@@ -0,0 +1,4 @@
+class ApplicationMailer < ActionMailer::Base
+ default from: "participacion@madrid.es"
+ layout 'mailer'
+end
diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb
new file mode 100644
index 000000000..fa53c7c1a
--- /dev/null
+++ b/app/mailers/mailer.rb
@@ -0,0 +1,16 @@
+class Mailer < ApplicationMailer
+
+ def comment(comment)
+ @comment = comment
+ @debate = comment.debate
+ mail(to: @debate.author.email, subject: t('mailer.comment.subject'))
+ end
+
+ def reply(reply)
+ @reply = reply
+ @debate = @reply.debate
+ parent = Comment.find(@reply.parent_id)
+ mail(to: parent.author.email, subject: t('mailer.reply.subject'))
+ end
+
+end
diff --git a/app/models/comment.rb b/app/models/comment.rb
index e99ef15e3..c2cf75292 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -17,4 +17,13 @@ class Comment < ActiveRecord::Base
def self.find_parent(params)
params[:commentable_type].constantize.find(params[:commentable_id])
end
+
+ def debate
+ commentable if commentable.class == Debate
+ end
+
+ def author
+ user
+ end
+
end
diff --git a/app/views/account/show.html.erb b/app/views/account/show.html.erb
index da568a9b9..d130121f3 100644
--- a/app/views/account/show.html.erb
+++ b/app/views/account/show.html.erb
@@ -15,6 +15,16 @@
<%= f.label :nickname, t("account.show.nickname_label") %>
<%= f.text_field :nickname %>
+
+ <%= f.check_box :email_on_debate_comment %>
+ <%= f.label :email_on_debate_comment, t("account.show.email_on_debate_comment_label") %>
+
+
+
+ <%= f.check_box :email_on_comment_reply %>
+ <%= f.label :email_on_comment_reply, t("account.show.email_on_comment_reply_label") %>
+
+
<%= f.submit t("account.show.save_changes_submit"), class: "button radius" %>
<% end %>
diff --git a/app/views/devise/menu/_login_items.html.erb b/app/views/devise/menu/_login_items.html.erb
index c075d23aa..4959553f9 100644
--- a/app/views/devise/menu/_login_items.html.erb
+++ b/app/views/devise/menu/_login_items.html.erb
@@ -1,14 +1,17 @@
- <% if user_signed_in? %>
- -
- <%= link_to(t("devise_views.menu.login_items.logout"), destroy_user_session_path, method: :delete) %>
-
- <% else %>
- -
- <%= link_to(t("devise_views.menu.login_items.login"), new_user_session_path) %>
-
- -
- <%= link_to(t("devise_views.menu.login_items.signup"), new_user_registration_path) %>
-
- <% end %>
+ <% if user_signed_in? %>
+ -
+ <%= link_to(t("layouts.header.my_account_link"), account_path) %>
+
+ -
+ <%= link_to(t("devise_views.menu.login_items.logout"), destroy_user_session_path, method: :delete) %>
+
+ <% else %>
+ -
+ <%= link_to(t("devise_views.menu.login_items.login"), new_user_session_path) %>
+
+ -
+ <%= link_to(t("devise_views.menu.login_items.signup"), new_user_registration_path, class: "button radius small") %>
+
+ <% end %>
\ No newline at end of file
diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb
index b76b2735e..48ffa41d5 100644
--- a/app/views/layouts/_header.html.erb
+++ b/app/views/layouts/_header.html.erb
@@ -1,53 +1,48 @@
+ <% if home_page? %>
+
+
+
<%= t("layouts.header.open_city") %>
+ <%= t("layouts.header.open_city_slogan") %>
+ <%= link_to t("layouts.header.create_debate"), new_debate_path, class: 'button radius' %>
+
+
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb
new file mode 100644
index 000000000..991cf0ffa
--- /dev/null
+++ b/app/views/layouts/mailer.html.erb
@@ -0,0 +1,5 @@
+
+
+ <%= yield %>
+
+
diff --git a/app/views/mailer/comment.html.erb b/app/views/mailer/comment.html.erb
new file mode 100644
index 000000000..f469d50b8
--- /dev/null
+++ b/app/views/mailer/comment.html.erb
@@ -0,0 +1,7 @@
+Hello,
+
+<%= @comment.author.name %>
+
+<%= @comment.body %>
+
+<%= link_to @debate.title, debate_url(@debate) %>
\ No newline at end of file
diff --git a/app/views/mailer/reply.html.erb b/app/views/mailer/reply.html.erb
new file mode 100644
index 000000000..7714d7c28
--- /dev/null
+++ b/app/views/mailer/reply.html.erb
@@ -0,0 +1,7 @@
+Hello,
+
+<%= @reply.author.name %>
+
+<%= @reply.body %>
+
+<%= link_to @debate.title, debate_url(@debate) %>
\ No newline at end of file
diff --git a/config/deploy-secrets.yml.example b/config/deploy-secrets.yml.example
new file mode 100644
index 000000000..b69fea225
--- /dev/null
+++ b/config/deploy-secrets.yml.example
@@ -0,0 +1,18 @@
+staging:
+ deploy_to: "/var/www/participacion"
+ ssh_port: 21
+ server: staging.participacion.madrid.es
+ user: xxxxx
+
+preproduction:
+ deploy_to: "/var/www/participacion"
+ ssh_port: 2222
+ server: xxx.xxx.xxx.xxx
+ user: xxxxx
+
+production:
+ deploy_to: "/var/www/participacion"
+ ssh_port: 2222
+ server: xxx.xxx.xxx.xxx
+ user: xxxxx
+
diff --git a/config/deploy.rb b/config/deploy.rb
new file mode 100644
index 000000000..8104d742f
--- /dev/null
+++ b/config/deploy.rb
@@ -0,0 +1,38 @@
+# config valid only for current version of Capistrano
+lock '3.4.0'
+
+def deploysecret(key)
+ @deploy_secrets_yml ||= YAML.load_file('config/deploy-secrets.yml')[fetch(:stage).to_s]
+ @deploy_secrets_yml[key.to_s]
+end
+
+set :rails_env, fetch(:stage)
+set :rvm_ruby_version, '2.2.2'
+
+set :application, 'participacion'
+set :repo_url, 'git@github.com:AyuntamientoMadrid/participacion.git'
+
+set :scm, :git
+set :revision, `git rev-parse --short #{fetch(:branch)}`.strip
+
+set :log_level, :info
+
+set :linked_files, %w{config/database.yml config/secrets.yml}
+set :linked_dirs, %w{log tmp public/system public/assets}
+
+set :keep_releases, 5
+
+set :local_user, ENV['USER']
+
+namespace :deploy do
+
+ after :restart, :clear_cache do
+ on roles(:web), in: :groups, limit: 3, wait: 10 do
+ # Here we can do anything such as:
+ # within release_path do
+ # execute :rake, 'cache:clear'
+ # end
+ end
+ end
+
+end
diff --git a/config/deploy/preproduction.rb b/config/deploy/preproduction.rb
new file mode 100644
index 000000000..fb9033c03
--- /dev/null
+++ b/config/deploy/preproduction.rb
@@ -0,0 +1,5 @@
+set :deploy_to, deploysecret(:deploy_to)
+set :branch, :production
+set :ssh_options, port: deploysecret(:ssh_port)
+
+server deploysecret(:server), user: deploysecret(:user), roles: %w(web app db importer)
\ No newline at end of file
diff --git a/config/deploy/production.rb b/config/deploy/production.rb
new file mode 100644
index 000000000..fb9033c03
--- /dev/null
+++ b/config/deploy/production.rb
@@ -0,0 +1,5 @@
+set :deploy_to, deploysecret(:deploy_to)
+set :branch, :production
+set :ssh_options, port: deploysecret(:ssh_port)
+
+server deploysecret(:server), user: deploysecret(:user), roles: %w(web app db importer)
\ No newline at end of file
diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb
new file mode 100644
index 000000000..5ca436c42
--- /dev/null
+++ b/config/deploy/staging.rb
@@ -0,0 +1,7 @@
+set :deploy_to, deploysecret(:deploy_to)
+set :branch, :master
+set :ssh_options, port: deploysecret(:ssh_port)
+
+set :passenger_restart_with_sudo, false
+
+server deploysecret(:server), user: deploysecret(:user), roles: %w(web app db importer)
diff --git a/config/locales/en.yml b/config/locales/en.yml
index fbb77d5a4..79e4e1129 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -11,6 +11,7 @@ en:
open_city_slogan: So the citizens can decide what kind of city they want.
create_debate: Create a debate
my_account_link: My account
+ language: Site language
admin:
dashboard:
index:
@@ -70,6 +71,8 @@ en:
show:
title: "My account"
save_changes_submit: "Save changes"
+ email_on_debate_comment_label: "Receive email when someone comments on my debates"
+ email_on_comment_reply_label: "Receive email when someone replies to my comments"
change_credentials_link: "Change my credentials"
first_name_label: "First Name"
last_name_label: "Last Name"
@@ -81,3 +84,8 @@ en:
shared:
tags_cloud:
tags: Tags
+ mailer:
+ comment:
+ subject: Someone has commented on your debate
+ reply:
+ subject: Someone has replied to your comment
diff --git a/config/locales/es.yml b/config/locales/es.yml
index c53d01547..8daf07d42 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -11,6 +11,7 @@ es:
open_city_slogan: Para que todos los madrileños decidamos que ciudad queremos tener.
create_debate: Crea un debate
my_account_link: Mi cuenta
+ language: Idioma de la página
admin:
dashboard:
index:
@@ -70,6 +71,8 @@ es:
show:
title: "Mi cuenta"
save_changes_submit: "Guardar cambios"
+ email_on_debate_comment_label: "Recibir un email cuando alguien commenta en mis debates"
+ email_on_comment_reply_label: "Recibir un email cuando alguien contesta a mis comentarios"
change_credentials_link: "Cambiar mi contraseña"
first_name_label: "Nombre"
last_name_label: "Apellidos"
@@ -81,4 +84,8 @@ es:
shared:
tags_cloud:
tags: Etiquetas
-
+ mailer:
+ comment:
+ subject: Alguien ha comentado en tu debate
+ reply:
+ subject: Alguien ha respondido a tu comentario
diff --git a/db/migrate/20150806163142_add_preferences_to_users.rb b/db/migrate/20150806163142_add_preferences_to_users.rb
new file mode 100644
index 000000000..8c3ae57cc
--- /dev/null
+++ b/db/migrate/20150806163142_add_preferences_to_users.rb
@@ -0,0 +1,6 @@
+class AddPreferencesToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :email_on_debate_comment, :boolean, default: false
+ add_column :users, :email_on_comment_reply, :boolean, default: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7833fc34c..6ee012197 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -94,6 +94,8 @@ ActiveRecord::Schema.define(version: 20150807140346) do
t.string "unconfirmed_email"
t.string "nickname"
t.boolean "use_nickname", default: false, null: false
+ t.boolean "email_on_debate_comment", default: false
+ t.boolean "email_on_comment_reply", default: false
end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
diff --git a/spec/features/account_spec.rb b/spec/features/account_spec.rb
index 7179b6c6b..e622c83c1 100644
--- a/spec/features/account_spec.rb
+++ b/spec/features/account_spec.rb
@@ -21,6 +21,8 @@ feature 'Account' do
fill_in 'account_first_name', with: 'Larry'
fill_in 'account_last_name', with: 'Bird'
+ check 'account_email_on_debate_comment'
+ check 'account_email_on_comment_reply'
click_button 'Save changes'
expect(page).to have_content "Saved"
@@ -29,5 +31,7 @@ feature 'Account' do
expect(page).to have_selector("input[value='Larry']")
expect(page).to have_selector("input[value='Bird']")
+ expect(page).to have_selector("input[id='account_email_on_debate_comment'][value='1']")
+ expect(page).to have_selector("input[id='account_email_on_comment_reply'][value='1']")
end
end
\ No newline at end of file
diff --git a/spec/features/comments_spec.rb b/spec/features/comments_spec.rb
index 3d215ef00..1ec6a8c10 100644
--- a/spec/features/comments_spec.rb
+++ b/spec/features/comments_spec.rb
@@ -41,11 +41,11 @@ feature 'Comments' do
login_as(user)
visit debate_path(debate)
- fill_in 'comment_body', with: '¿Has pensado en esto...?'
+ fill_in 'comment_body', with: 'Have you thought about...?'
click_button 'Publish comment'
within "#comments" do
- expect(page).to have_content '¿Has pensado en esto...?'
+ expect(page).to have_content 'Have you thought about...?'
end
end
@@ -60,12 +60,12 @@ feature 'Comments' do
click_link "Reply"
within "#js-comment-form-comment_#{comment.id}" do
- fill_in 'comment_body', with: 'La semana que viene está hecho.'
+ fill_in 'comment_body', with: 'It will be done next week.'
click_button 'Publish reply'
end
within "#comment-#{comment.id}" do
- expect(page).to have_content 'La semana que viene está hecho.'
+ expect(page).to have_content 'It will be done next week.'
end
end
diff --git a/spec/features/emails_spec.rb b/spec/features/emails_spec.rb
new file mode 100644
index 000000000..86c794fac
--- /dev/null
+++ b/spec/features/emails_spec.rb
@@ -0,0 +1,63 @@
+require 'rails_helper'
+
+feature 'Emails' do
+
+ background do
+ reset_mailer
+ end
+
+ scenario "Signup Email" do
+ sign_up
+
+ email = open_last_email
+ expect(email).to have_subject('Confirmation instructions')
+ expect(email).to deliver_to('manuela@madrid.es')
+ expect(email).to have_body_text(user_confirmation_path)
+ end
+
+ scenario "Reset password" do
+ reset_password
+
+ email = open_last_email
+ expect(email).to have_subject('Reset password instructions')
+ expect(email).to deliver_to('manuela@madrid.es')
+ expect(email).to have_body_text(edit_user_password_path)
+ end
+
+ scenario "Debate comment", :js do
+ user = create(:user, email_on_debate_comment: true)
+ debate = create(:debate, author: user)
+ comment_on(debate)
+
+ email = open_last_email
+ expect(email).to have_subject('Someone has commented on your debate')
+ expect(email).to deliver_to(debate.author)
+ expect(email).to have_body_text(debate_path(debate))
+ end
+
+ scenario "Comment reply", :js do
+ user = create(:user, email_on_comment_reply: true)
+ reply_to(user)
+
+ email = open_last_email
+ expect(email).to have_subject('Someone has replied to your comment')
+ expect(email).to deliver_to(user)
+ expect(email).to have_body_text(debate_path(Comment.first.debate))
+ end
+
+ scenario 'Do not send email about debate comment unless set in preferences', :js do
+ user = create(:user, email_on_debate_comment: false)
+ debate = create(:debate, author: user)
+ comment_on(debate)
+
+ expect { open_last_email }.to raise_error "No email has been sent!"
+ end
+
+ scenario "Do not send email about comment reply unless set in preferences", :js do
+ user = create(:user, email_on_comment_reply: false)
+ reply_to(user)
+
+ expect { open_last_email }.to raise_error "No email has been sent!"
+ end
+
+end
\ No newline at end of file
diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb
index d2f01ec84..c15869bae 100644
--- a/spec/features/users_spec.rb
+++ b/spec/features/users_spec.rb
@@ -44,4 +44,26 @@ feature 'Users' do
expect(page).to have_content 'Signed out successfully.'
end
+ scenario 'Reset password' do
+ create(:user, email: 'manuela@madrid.es')
+
+ visit '/'
+ click_link 'Log in'
+ click_link 'Forgot your password?'
+
+ fill_in 'user_email', with: 'manuela@madrid.es'
+ click_button 'Send me reset password instructions'
+
+ expect(page).to have_content "You will receive an email with instructions on how to reset your password in a few minutes."
+
+ sent_token = /.*reset_password_token=(.*)".*/.match(ActionMailer::Base.deliveries.last.body.to_s)[1]
+ visit edit_user_password_path(reset_password_token: sent_token)
+
+ fill_in 'user_password', with: 'new password'
+ fill_in 'user_password_confirmation', with: 'new password'
+ click_button 'Change my password'
+
+ expect(page).to have_content "Your password has been changed successfully. You are now signed in."
+ end
+
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index e53871fe2..9387c2bed 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -34,6 +34,20 @@ describe User do
expect(subject).to be_valid
end
+ describe 'preferences' do
+ describe 'email_on_debate_comment' do
+ it 'should be false by default' do
+ expect(subject.email_on_debate_comment).to eq(false)
+ end
+ end
+
+ describe 'email_on_comment_reply' do
+ it 'should be false by default' do
+ expect(subject.email_on_comment_reply).to eq(false)
+ end
+ end
+ end
+
describe 'use_nickname' do
describe 'when true' do
before { subject.use_nickname = true }
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 156073f78..640f9e96c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,5 +1,7 @@
require 'factory_girl_rails'
require 'database_cleaner'
+require "email_spec"
+Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
RSpec.configure do |config|
config.use_transactional_fixtures = false
@@ -7,7 +9,9 @@ RSpec.configure do |config|
config.filter_run :focus
config.run_all_when_everything_filtered = true
config.include FactoryGirl::Syntax::Methods
-
+ config.include(EmailSpec::Helpers)
+ config.include(EmailSpec::Matchers)
+ config.include(CommonActions)
config.before(:suite) do
DatabaseCleaner.clean_with :truncation
end
diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb
new file mode 100644
index 000000000..d07f60261
--- /dev/null
+++ b/spec/support/common_actions.rb
@@ -0,0 +1,54 @@
+module CommonActions
+
+ def sign_up
+ visit '/'
+ click_link 'Sign up'
+
+ fill_in 'user_first_name', with: 'Manuela'
+ fill_in 'user_last_name', with: 'Carmena'
+ fill_in 'user_email', with: 'manuela@madrid.es'
+ fill_in 'user_password', with: 'judgementday'
+ fill_in 'user_password_confirmation', with: 'judgementday'
+
+ click_button 'Sign up'
+ end
+
+ def reset_password
+ create(:user, email: 'manuela@madrid.es')
+
+ visit '/'
+ click_link 'Log in'
+ click_link 'Forgot your password?'
+
+ fill_in 'user_email', with: 'manuela@madrid.es'
+ click_button 'Send me reset password instructions'
+ end
+
+ def comment_on(debate)
+ user2 = create(:user)
+
+ login_as(user2)
+ visit debate_path(debate)
+
+ fill_in 'comment_body', with: 'Have you thought about...?'
+ click_button 'Publish comment'
+ expect(page).to have_content 'Have you thought about...?'
+ end
+
+ def reply_to(user)
+ manuela = create(:user)
+ debate = create(:debate)
+ comment = create(:comment, commentable: debate, user: user)
+
+ login_as(manuela)
+ visit debate_path(debate)
+
+ click_link "Reply"
+ within "#js-comment-form-comment_#{comment.id}" do
+ fill_in 'comment_body', with: 'It will be done next week.'
+ click_button 'Publish reply'
+ end
+ expect(page).to have_content 'It will be done next week.'
+ end
+
+end
\ No newline at end of file