From c9b8a58e3fa1cc211f76f73af4f2e66684733b3f Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 14 Sep 2016 13:53:35 +0200 Subject: [PATCH 01/66] creates polling officers from admin --- .../admin/poll/officers_controller.rb | 32 +++++++++++++ app/helpers/admin_helper.rb | 2 +- app/models/abilities/administrator.rb | 1 + app/models/poll.rb | 2 + app/models/poll/officer.rb | 8 ++++ app/views/admin/_menu.html.erb | 6 +++ app/views/admin/poll/_menu.html.erb | 1 + .../admin/poll/officers/_officer.html.erb | 26 +++++++++++ app/views/admin/poll/officers/index.html.erb | 46 +++++++++++++++++++ app/views/admin/poll/officers/search.js.erb | 1 + .../admin/poll/officers/user_not_found.js.erb | 1 + config/locales/admin.en.yml | 11 +++++ config/locales/admin.es.yml | 11 +++++ config/routes.rb | 6 +++ db/migrate/20160914110004_create_polls.rb | 7 +++ .../20160914110039_create_poll_officers.rb | 7 +++ db/schema.rb | 10 +++- spec/factories.rb | 4 ++ spec/features/admin/poll/officers_spec.rb | 36 +++++++++++++++ 19 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 app/controllers/admin/poll/officers_controller.rb create mode 100644 app/models/poll.rb create mode 100644 app/models/poll/officer.rb create mode 100644 app/views/admin/poll/_menu.html.erb create mode 100644 app/views/admin/poll/officers/_officer.html.erb create mode 100644 app/views/admin/poll/officers/index.html.erb create mode 100644 app/views/admin/poll/officers/search.js.erb create mode 100644 app/views/admin/poll/officers/user_not_found.js.erb create mode 100644 db/migrate/20160914110004_create_polls.rb create mode 100644 db/migrate/20160914110039_create_poll_officers.rb create mode 100644 spec/features/admin/poll/officers_spec.rb diff --git a/app/controllers/admin/poll/officers_controller.rb b/app/controllers/admin/poll/officers_controller.rb new file mode 100644 index 000000000..5495d390c --- /dev/null +++ b/app/controllers/admin/poll/officers_controller.rb @@ -0,0 +1,32 @@ +class Admin::Poll::OfficersController < Admin::BaseController + load_and_authorize_resource :officer, class: "Poll::Officer" + + def index + @officers = @officers.page(params[:page]) + end + + def search + @user = User.find_by(email: params[:email]) + + respond_to do |format| + if @user + @officer = Poll::Officer.find_or_initialize_by(user: @user) + format.js + else + format.js { render "user_not_found" } + end + end + end + + def create + @officer.user_id = params[:user_id] + @officer.save + + redirect_to admin_poll_officers_path + end + + def destroy + @officer.destroy + redirect_to admin_poll_officers_path + end +end \ No newline at end of file diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index 515a54deb..39ab74b96 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -19,7 +19,7 @@ module AdminHelper private def namespace - controller.class.parent.name.downcase + controller.class.parent.name.downcase.gsub("::", "/") end end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 0dfce6d3e..0f1100137 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -38,6 +38,7 @@ module Abilities can [:search, :create, :index, :destroy], ::Moderator can [:search, :create, :index, :summary], ::Valuator can [:search, :create, :index, :destroy], ::Manager + can [:search, :create, :index, :destroy], ::Poll::Officer can :manage, Annotation diff --git a/app/models/poll.rb b/app/models/poll.rb new file mode 100644 index 000000000..d815cba49 --- /dev/null +++ b/app/models/poll.rb @@ -0,0 +1,2 @@ +class Poll < ActiveRecord::Base +end \ No newline at end of file diff --git a/app/models/poll/officer.rb b/app/models/poll/officer.rb new file mode 100644 index 000000000..d6fe5730a --- /dev/null +++ b/app/models/poll/officer.rb @@ -0,0 +1,8 @@ +class Poll + class Officer < ActiveRecord::Base + belongs_to :user + delegate :name, :email, to: :user + + validates :user_id, presence: true, uniqueness: true + end +end \ No newline at end of file diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 7ea48b2c6..40bcc6330 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -83,6 +83,12 @@ <% end %> +
  • > + <%= link_to admin_poll_officers_path do %> + <%= t('admin.menu.poll_officers') %> + <% end %> +
  • +
  • > <%= link_to admin_activity_path do %> <%= t('admin.menu.activity') %> diff --git a/app/views/admin/poll/_menu.html.erb b/app/views/admin/poll/_menu.html.erb new file mode 100644 index 000000000..08efd87dc --- /dev/null +++ b/app/views/admin/poll/_menu.html.erb @@ -0,0 +1 @@ +<%= render "admin/menu" %> \ No newline at end of file diff --git a/app/views/admin/poll/officers/_officer.html.erb b/app/views/admin/poll/officers/_officer.html.erb new file mode 100644 index 000000000..c9251548d --- /dev/null +++ b/app/views/admin/poll/officers/_officer.html.erb @@ -0,0 +1,26 @@ +
    + + + + + + + + +
    + <%= officer.name %> + + <%= officer.email %> + + <% if officer.persisted? %> + <%= link_to t('admin.poll_officers.officer.delete'), + admin_poll_officer_path(officer), + method: :delete, + class: "button hollow alert" %> + <% else %> + <%= link_to t('admin.poll_officers.officer.add'),{ controller: "admin/poll/officers", action: :create, user_id: officer.user_id }, + method: :post, + class: "button success" %> + <% end %> +
    +
    diff --git a/app/views/admin/poll/officers/index.html.erb b/app/views/admin/poll/officers/index.html.erb new file mode 100644 index 000000000..c330741af --- /dev/null +++ b/app/views/admin/poll/officers/index.html.erb @@ -0,0 +1,46 @@ +

    <%= t("admin.poll_officers.index.title") %>

    + +
    + <%= form_tag search_admin_poll_officers_path, method: :get, remote: true do %> +
    + <%= text_field_tag :email, '', placeholder: t('admin.poll_officers.search.email_placeholder') %> +
    +
    + <%= submit_tag t('admin.poll_officers.search.search'), class: 'button' %> +
    + <% end %> +
    + +
    + +

    <%= page_entries_info @officers %>

    + + + <% @officers.each do |officer| %> + + + + + + <% end %> +
    + <%= officer.name %> + + <%= officer.email %> + + <% if officer.persisted? %> + <%= link_to t('admin.poll_officers.officer.delete'), + admin_poll_officer_path(officer), + method: :delete, + class: "button hollow alert" + %> + <% else %> + <%= link_to t('admin.poll_officers.officer.add'), + { controller: "admin/poll/officers", action: :create, + user_id: officer.user_id }, + method: :post, + class: "button success" %> + <% end %> +
    + +<%= paginate @officers %> diff --git a/app/views/admin/poll/officers/search.js.erb b/app/views/admin/poll/officers/search.js.erb new file mode 100644 index 000000000..bd259f7fb --- /dev/null +++ b/app/views/admin/poll/officers/search.js.erb @@ -0,0 +1 @@ +$("#search-result").html("<%= j render 'officer', officer: @officer %>"); diff --git a/app/views/admin/poll/officers/user_not_found.js.erb b/app/views/admin/poll/officers/user_not_found.js.erb new file mode 100644 index 000000000..108f75295 --- /dev/null +++ b/app/views/admin/poll/officers/user_not_found.js.erb @@ -0,0 +1 @@ +$("#search-result").html("
    <%= j t('admin.officers.search.user_not_found') %>
    "); diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 2f73f64d8..97723c9c8 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -105,6 +105,7 @@ en: managers: Managers moderators: Moderators valuators: Valuators + poll_officers: Poll officers officials: Officials organizations: Organisations settings: Configuration settings @@ -140,6 +141,16 @@ en: in_evaluation_count: In evaluation total_count: Total cost: Cost + poll_officers: + index: + title: Poll officers + officer: + add: Add + delete: Delete + search: + email_placeholder: Search user by email + search: Search + user_not_found: User not found officials: edit: destroy: Remove 'Official' status diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 5aada1ce1..f71293208 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -103,6 +103,7 @@ es: managers: Gestores moderators: Moderadores valuators: Evaluadores + poll_officers: Presidentes de mesa officials: Cargos públicos organizations: Organizaciones settings: Configuración global @@ -138,6 +139,16 @@ es: in_evaluation_count: En evaluación total_count: Total cost: Coste total + poll_officers: + index: + title: Presidentes de mesa + officer: + add: Añadir como Presidente de mesa + delete: Borrar + search: + email_placeholder: Buscar usuario por email + search: Buscar + user_not_found: Usuario no encontrado officials: edit: destroy: Eliminar condición de 'Cargo Público' diff --git a/config/routes.rb b/config/routes.rb index 4f3eb94ec..46deae30b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -177,6 +177,12 @@ Rails.application.routes.draw do get :search, on: :collection end + namespace :poll do + resources :officers, only: [:index, :create, :destroy] do + get :search, on: :collection + end + end + resources :verifications, controller: :verifications, only: :index do get :search, on: :collection end diff --git a/db/migrate/20160914110004_create_polls.rb b/db/migrate/20160914110004_create_polls.rb new file mode 100644 index 000000000..9dd67d9ba --- /dev/null +++ b/db/migrate/20160914110004_create_polls.rb @@ -0,0 +1,7 @@ +class CreatePolls < ActiveRecord::Migration + def change + create_table :polls do |t| + t.string :name + end + end +end diff --git a/db/migrate/20160914110039_create_poll_officers.rb b/db/migrate/20160914110039_create_poll_officers.rb new file mode 100644 index 000000000..329220d40 --- /dev/null +++ b/db/migrate/20160914110039_create_poll_officers.rb @@ -0,0 +1,7 @@ +class CreatePollOfficers < ActiveRecord::Migration + def change + create_table :poll_officers do |t| + t.integer :user_id + end + end +end diff --git a/db/schema.rb b/db/schema.rb index becde4f8a..082292471 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160803154011) do +ActiveRecord::Schema.define(version: 20160914110039) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -270,6 +270,14 @@ ActiveRecord::Schema.define(version: 20160803154011) do add_index "organizations", ["user_id"], name: "index_organizations_on_user_id", using: :btree + create_table "poll_officers", force: :cascade do |t| + t.integer "user_id" + end + + create_table "polls", force: :cascade do |t| + t.string "name" + end + create_table "proposal_notifications", force: :cascade do |t| t.string "title" t.text "body" diff --git a/spec/factories.rb b/spec/factories.rb index cdcfe7381..00884733e 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -259,6 +259,10 @@ FactoryGirl.define do user end + factory :poll_officer, class: 'Poll::Officer' do + user + end + factory :organization do user responsible_name "Johnny Utah" diff --git a/spec/features/admin/poll/officers_spec.rb b/spec/features/admin/poll/officers_spec.rb new file mode 100644 index 000000000..ed9ec545d --- /dev/null +++ b/spec/features/admin/poll/officers_spec.rb @@ -0,0 +1,36 @@ +require 'rails_helper' + +feature 'Admin poll officers' do + background do + @admin = create(:administrator) + @user = create(:user, username: 'Pedro Jose Garcia') + @officer = create(:poll_officer) + login_as(@admin.user) + visit admin_poll_officers_path + end + + scenario 'Index' do + expect(page).to have_content @officer.name + expect(page).to have_content @officer.email + expect(page).to_not have_content @user.name + end + + scenario 'Create poll officer', :js do + fill_in 'email', with: @user.email + click_button 'Search' + + expect(page).to have_content @user.name + click_link 'Add' + within("#officers") do + expect(page).to have_content @user.name + end + end + + scenario 'Delete poll officer' do + click_link 'Delete' + + within("#officers") do + expect(page).to_not have_content @officer.name + end + end +end \ No newline at end of file From cd5266046b0d34600e8910e2d2e5f66382bc1fce Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 14 Sep 2016 14:25:38 +0200 Subject: [PATCH 02/66] fixes translation key --- app/views/admin/poll/officers/user_not_found.js.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/poll/officers/user_not_found.js.erb b/app/views/admin/poll/officers/user_not_found.js.erb index 108f75295..40b6caac5 100644 --- a/app/views/admin/poll/officers/user_not_found.js.erb +++ b/app/views/admin/poll/officers/user_not_found.js.erb @@ -1 +1 @@ -$("#search-result").html("
    <%= j t('admin.officers.search.user_not_found') %>
    "); +$("#search-result").html("
    <%= j t('admin.poll_officers.search.user_not_found') %>
    "); From b5bebaa6c78df367ec117ef94be584a539dd6a18 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Fri, 16 Sep 2016 13:06:30 +0200 Subject: [PATCH 03/66] adds view placeholders for officing polls --- .../admin/poll/booths_controller.rb | 16 ++++++++++++++++ .../admin/poll/officers_controller.rb | 9 ++++++++- app/controllers/admin/poll/polls_controller.rb | 16 ++++++++++++++++ app/controllers/officing/base_controller.rb | 18 ++++++++++++++++++ .../officing/dashboard_controller.rb | 6 ++++++ app/controllers/officing/results_controller.rb | 15 +++++++++++++++ app/controllers/officing/voters_controller.rb | 9 +++++++++ app/views/admin/_menu.html.erb | 16 ++++++++++++++-- app/views/admin/poll/booths/edit.html.erb | 1 + app/views/admin/poll/booths/index.html.erb | 1 + app/views/admin/poll/booths/new.html.erb | 1 + app/views/admin/poll/booths/show.html.erb | 1 + app/views/admin/poll/officers/edit.html.erb | 1 + app/views/admin/poll/officers/show.html.erb | 1 + app/views/admin/poll/polls/edit.html.erb | 1 + app/views/admin/poll/polls/index.html.erb | 1 + app/views/admin/poll/polls/new.html.erb | 1 + app/views/admin/poll/polls/show.html.erb | 1 + app/views/officing/_menu.html.erb | 18 ++++++++++++++++++ app/views/officing/dashboard/index.html.erb | 6 ++++++ app/views/officing/results/index.html.erb | 1 + app/views/officing/results/new.html.erb | 1 + app/views/officing/results/show.html.erb | 1 + app/views/officing/voters/new.html.erb | 1 + app/views/officing/voters/show.html.erb | 1 + app/views/poll/voters/new.html.erb | 1 + app/views/shared/_admin_login_items.html.erb | 6 ++++++ config/locales/admin.en.yml | 2 ++ config/locales/admin.es.yml | 2 ++ config/locales/en.yml | 1 + config/locales/es.yml | 1 + config/locales/officing.en.yml | 10 ++++++++++ config/locales/officing.es.yml | 10 ++++++++++ config/routes.rb | 17 ++++++++++++++--- 34 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 app/controllers/admin/poll/booths_controller.rb create mode 100644 app/controllers/admin/poll/polls_controller.rb create mode 100644 app/controllers/officing/base_controller.rb create mode 100644 app/controllers/officing/dashboard_controller.rb create mode 100644 app/controllers/officing/results_controller.rb create mode 100644 app/controllers/officing/voters_controller.rb create mode 100644 app/views/admin/poll/booths/edit.html.erb create mode 100644 app/views/admin/poll/booths/index.html.erb create mode 100644 app/views/admin/poll/booths/new.html.erb create mode 100644 app/views/admin/poll/booths/show.html.erb create mode 100644 app/views/admin/poll/officers/edit.html.erb create mode 100644 app/views/admin/poll/officers/show.html.erb create mode 100644 app/views/admin/poll/polls/edit.html.erb create mode 100644 app/views/admin/poll/polls/index.html.erb create mode 100644 app/views/admin/poll/polls/new.html.erb create mode 100644 app/views/admin/poll/polls/show.html.erb create mode 100644 app/views/officing/_menu.html.erb create mode 100644 app/views/officing/dashboard/index.html.erb create mode 100644 app/views/officing/results/index.html.erb create mode 100644 app/views/officing/results/new.html.erb create mode 100644 app/views/officing/results/show.html.erb create mode 100644 app/views/officing/voters/new.html.erb create mode 100644 app/views/officing/voters/show.html.erb create mode 100644 app/views/poll/voters/new.html.erb create mode 100644 config/locales/officing.en.yml create mode 100644 config/locales/officing.es.yml diff --git a/app/controllers/admin/poll/booths_controller.rb b/app/controllers/admin/poll/booths_controller.rb new file mode 100644 index 000000000..9b1e62f8f --- /dev/null +++ b/app/controllers/admin/poll/booths_controller.rb @@ -0,0 +1,16 @@ +class Admin::Poll::BoothsController < Admin::BaseController + skip_authorization_check + + def index + end + + def show + end + + def new + end + + def edit + end + +end \ No newline at end of file diff --git a/app/controllers/admin/poll/officers_controller.rb b/app/controllers/admin/poll/officers_controller.rb index 5495d390c..7f6f918d7 100644 --- a/app/controllers/admin/poll/officers_controller.rb +++ b/app/controllers/admin/poll/officers_controller.rb @@ -1,5 +1,5 @@ class Admin::Poll::OfficersController < Admin::BaseController - load_and_authorize_resource :officer, class: "Poll::Officer" + load_and_authorize_resource :officer, class: "Poll::Officer", except: [:edit, :show] def index @officers = @officers.page(params[:page]) @@ -29,4 +29,11 @@ class Admin::Poll::OfficersController < Admin::BaseController @officer.destroy redirect_to admin_poll_officers_path end + + def show + end + + def edit + end + end \ No newline at end of file diff --git a/app/controllers/admin/poll/polls_controller.rb b/app/controllers/admin/poll/polls_controller.rb new file mode 100644 index 000000000..b90fd2c11 --- /dev/null +++ b/app/controllers/admin/poll/polls_controller.rb @@ -0,0 +1,16 @@ +class Admin::Poll::PollsController < Admin::BaseController + skip_authorization_check + + def index + end + + def show + end + + def new + end + + def edit + end + +end \ No newline at end of file diff --git a/app/controllers/officing/base_controller.rb b/app/controllers/officing/base_controller.rb new file mode 100644 index 000000000..5aeb2431c --- /dev/null +++ b/app/controllers/officing/base_controller.rb @@ -0,0 +1,18 @@ +class Officing::BaseController < ActionController::Base + layout 'admin' + + #before_action :verify_officer + before_action :set_locale + + private + + def set_locale + if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym) + session[:locale] = params[:locale] + end + + session[:locale] ||= I18n.default_locale + + I18n.locale = session[:locale] + end +end \ No newline at end of file diff --git a/app/controllers/officing/dashboard_controller.rb b/app/controllers/officing/dashboard_controller.rb new file mode 100644 index 000000000..4d80a974a --- /dev/null +++ b/app/controllers/officing/dashboard_controller.rb @@ -0,0 +1,6 @@ +class Officing::DashboardController < Officing::BaseController + + def index + end + +end diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb new file mode 100644 index 000000000..03e638366 --- /dev/null +++ b/app/controllers/officing/results_controller.rb @@ -0,0 +1,15 @@ +class Officing::ResultsController < Officing::BaseController + layout 'admin' + + before_action :authenticate_user! + + def index + end + + def show + end + + def new + end + +end \ No newline at end of file diff --git a/app/controllers/officing/voters_controller.rb b/app/controllers/officing/voters_controller.rb new file mode 100644 index 000000000..6d7ad8512 --- /dev/null +++ b/app/controllers/officing/voters_controller.rb @@ -0,0 +1,9 @@ +class Officing::VotersController < Officing::BaseController + layout 'admin' + + before_action :authenticate_user! + + def new + end + +end \ No newline at end of file diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 40bcc6330..48736c378 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -83,12 +83,24 @@ <% end %>
  • -
  • > - <%= link_to admin_poll_officers_path do %> +
  • > + <%= link_to admin_poll_officers_path(Poll.last) do %> <%= t('admin.menu.poll_officers') %> <% end %>
  • +
  • > + <%= link_to admin_polls_path do %> + <%= t('admin.menu.polls') %> + <% end %> +
  • + +
  • > + <%= link_to admin_poll_booths_url(Poll.last) do %> + <%= t('admin.menu.booths') %> + <% end %> +
  • +
  • > <%= link_to admin_activity_path do %> <%= t('admin.menu.activity') %> diff --git a/app/views/admin/poll/booths/edit.html.erb b/app/views/admin/poll/booths/edit.html.erb new file mode 100644 index 000000000..4f66c61cd --- /dev/null +++ b/app/views/admin/poll/booths/edit.html.erb @@ -0,0 +1 @@ +booth edit \ No newline at end of file diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb new file mode 100644 index 000000000..7ef71767d --- /dev/null +++ b/app/views/admin/poll/booths/index.html.erb @@ -0,0 +1 @@ +booth index \ No newline at end of file diff --git a/app/views/admin/poll/booths/new.html.erb b/app/views/admin/poll/booths/new.html.erb new file mode 100644 index 000000000..ebcb88bd4 --- /dev/null +++ b/app/views/admin/poll/booths/new.html.erb @@ -0,0 +1 @@ +booth new \ No newline at end of file diff --git a/app/views/admin/poll/booths/show.html.erb b/app/views/admin/poll/booths/show.html.erb new file mode 100644 index 000000000..791a97e48 --- /dev/null +++ b/app/views/admin/poll/booths/show.html.erb @@ -0,0 +1 @@ +booth show \ No newline at end of file diff --git a/app/views/admin/poll/officers/edit.html.erb b/app/views/admin/poll/officers/edit.html.erb new file mode 100644 index 000000000..5c64d3aeb --- /dev/null +++ b/app/views/admin/poll/officers/edit.html.erb @@ -0,0 +1 @@ +officer edit \ No newline at end of file diff --git a/app/views/admin/poll/officers/show.html.erb b/app/views/admin/poll/officers/show.html.erb new file mode 100644 index 000000000..fc702276e --- /dev/null +++ b/app/views/admin/poll/officers/show.html.erb @@ -0,0 +1 @@ +officer show \ No newline at end of file diff --git a/app/views/admin/poll/polls/edit.html.erb b/app/views/admin/poll/polls/edit.html.erb new file mode 100644 index 000000000..ca0a8dc14 --- /dev/null +++ b/app/views/admin/poll/polls/edit.html.erb @@ -0,0 +1 @@ +poll edit \ No newline at end of file diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb new file mode 100644 index 000000000..d01cf64f1 --- /dev/null +++ b/app/views/admin/poll/polls/index.html.erb @@ -0,0 +1 @@ +polls index \ No newline at end of file diff --git a/app/views/admin/poll/polls/new.html.erb b/app/views/admin/poll/polls/new.html.erb new file mode 100644 index 000000000..6e11970d3 --- /dev/null +++ b/app/views/admin/poll/polls/new.html.erb @@ -0,0 +1 @@ +poll new \ No newline at end of file diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb new file mode 100644 index 000000000..61c9d5afb --- /dev/null +++ b/app/views/admin/poll/polls/show.html.erb @@ -0,0 +1 @@ +poll show \ No newline at end of file diff --git a/app/views/officing/_menu.html.erb b/app/views/officing/_menu.html.erb new file mode 100644 index 000000000..81734d99f --- /dev/null +++ b/app/views/officing/_menu.html.erb @@ -0,0 +1,18 @@ +
    +
      + +
    • > + <%= link_to new_officing_poll_voter_path(Poll.last) do %> + + <%= t("officing.menu.voters") %> + <% end %> +
    • + +
    • > + <%= link_to new_officing_poll_result_path(Poll.last) do %> + + <%= t("officing.menu.results") %> + <% end %> +
    • + +
    diff --git a/app/views/officing/dashboard/index.html.erb b/app/views/officing/dashboard/index.html.erb new file mode 100644 index 000000000..cf014d719 --- /dev/null +++ b/app/views/officing/dashboard/index.html.erb @@ -0,0 +1,6 @@ +
    +

    <%= t("officing.dashboard.index.title") %>

    + +

    <%= t("officing.dashboard.index.info") %>

    + +
    diff --git a/app/views/officing/results/index.html.erb b/app/views/officing/results/index.html.erb new file mode 100644 index 000000000..8e9faa1ab --- /dev/null +++ b/app/views/officing/results/index.html.erb @@ -0,0 +1 @@ +results index \ No newline at end of file diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb new file mode 100644 index 000000000..bb40dff9e --- /dev/null +++ b/app/views/officing/results/new.html.erb @@ -0,0 +1 @@ +results new \ No newline at end of file diff --git a/app/views/officing/results/show.html.erb b/app/views/officing/results/show.html.erb new file mode 100644 index 000000000..b3ca8e29c --- /dev/null +++ b/app/views/officing/results/show.html.erb @@ -0,0 +1 @@ +results show \ No newline at end of file diff --git a/app/views/officing/voters/new.html.erb b/app/views/officing/voters/new.html.erb new file mode 100644 index 000000000..0fb4c6bc3 --- /dev/null +++ b/app/views/officing/voters/new.html.erb @@ -0,0 +1 @@ +voters new diff --git a/app/views/officing/voters/show.html.erb b/app/views/officing/voters/show.html.erb new file mode 100644 index 000000000..fd8c83123 --- /dev/null +++ b/app/views/officing/voters/show.html.erb @@ -0,0 +1 @@ +voters show \ No newline at end of file diff --git a/app/views/poll/voters/new.html.erb b/app/views/poll/voters/new.html.erb new file mode 100644 index 000000000..596b8769c --- /dev/null +++ b/app/views/poll/voters/new.html.erb @@ -0,0 +1 @@ +new.html.erb \ No newline at end of file diff --git a/app/views/shared/_admin_login_items.html.erb b/app/views/shared/_admin_login_items.html.erb index 6ba10bbca..cfe3cc1c9 100644 --- a/app/views/shared/_admin_login_items.html.erb +++ b/app/views/shared/_admin_login_items.html.erb @@ -22,4 +22,10 @@ <%= link_to t("layouts.header.management"), management_sign_in_path %>
  • <% end %> + + <%# if current_user.administrator? || current_user.officer? %> +
  • + <%= link_to t("layouts.header.officing"), officing_root_path %> +
  • + <%# end %> <% end %> diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 97723c9c8..a04595e8b 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -106,6 +106,8 @@ en: moderators: Moderators valuators: Valuators poll_officers: Poll officers + polls: Polls + booths: Booths officials: Officials organizations: Organisations settings: Configuration settings diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index f71293208..ba3548215 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -104,6 +104,8 @@ es: moderators: Moderadores valuators: Evaluadores poll_officers: Presidentes de mesa + polls: Votaciones + booths: Urnas officials: Cargos públicos organizations: Organizaciones settings: Configuración global diff --git a/config/locales/en.yml b/config/locales/en.yml index 3a16722dc..45ec5fac0 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -195,6 +195,7 @@ en: management: Management moderation: Moderation valuation: Valuation + officing: Polling officers more_information: More information my_account_link: My account my_activity_link: My activity diff --git a/config/locales/es.yml b/config/locales/es.yml index 993ee8e95..7cb02f035 100755 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -195,6 +195,7 @@ es: management: Gestión moderation: Moderar valuation: Evaluación + officing: Presidentes de mesa more_information: Más información my_account_link: Mi cuenta my_activity_link: Mi actividad diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml new file mode 100644 index 000000000..532d18498 --- /dev/null +++ b/config/locales/officing.en.yml @@ -0,0 +1,10 @@ +--- +en: + officing: + dashboard: + index: + title: Poll officing + info: Here you can validate user documents and store voting results + menu: + voters: Validate citizen document + results: Store voting results \ No newline at end of file diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml new file mode 100644 index 000000000..baa60b106 --- /dev/null +++ b/config/locales/officing.es.yml @@ -0,0 +1,10 @@ +--- +es: + officing: + dashboard: + index: + title: Presidir mesa de votaciones + info: Aquí puedes validar documentos de ciudadanos y guardar los resultados de las urnas + menu: + voters: Validar documento de identidad + results: Guardar resultados de la votación \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 46deae30b..befbda11e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -177,9 +177,12 @@ Rails.application.routes.draw do get :search, on: :collection end - namespace :poll do - resources :officers, only: [:index, :create, :destroy] do - get :search, on: :collection + scope module: 'poll' do + resources :polls do + resources :booths + resources :officers do + get :search, on: :collection + end end end @@ -266,6 +269,14 @@ Rails.application.routes.draw do end end + namespace :officing do + resources :polls do + resources :voters, only: [:new, :show] + resources :results, only: [:new, :index, :show] + end + root to: "dashboard#index" + end + if Rails.env.development? mount LetterOpenerWeb::Engine, at: "/letter_opener" end From 4ebb4a1104e52552b54f8166160b8e1304aaecb2 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Fri, 16 Sep 2016 13:06:39 +0200 Subject: [PATCH 04/66] updates dev_seeds with polls --- db/dev_seeds.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index 61b5f5060..beb1d815f 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -336,3 +336,9 @@ Proposal.last(3).each do |proposal| created_at: rand((Time.now - 1.week) .. Time.now)) puts " #{banner.title}" end + +puts "Creating polls" + +3.times.each_with_index do |i| + Poll.create(name: "Poll #{i}") +end \ No newline at end of file From 5ff3e2c5990c1f91b3fdd06c2c5f381cf29b86f5 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Fri, 16 Sep 2016 19:07:12 +0200 Subject: [PATCH 05/66] Adds i18n and styles to admin polls index and new --- app/views/admin/poll/polls/index.html.erb | 37 ++++++++++++++++++++++- app/views/admin/poll/polls/new.html.erb | 37 ++++++++++++++++++++++- config/locales/admin.en.yml | 15 +++++++++ config/locales/admin.es.yml | 15 +++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb index d01cf64f1..8ba763356 100644 --- a/app/views/admin/poll/polls/index.html.erb +++ b/app/views/admin/poll/polls/index.html.erb @@ -1 +1,36 @@ -polls index \ No newline at end of file +

    <%= t("admin.polls.index.title") %>

    + +<%= link_to t("admin.polls.index.create"), new_admin_poll_path, class: "button success float-right" %> + + +
    + <%= t("admin.polls.index.no_polls") %> +
    + + + + + + + + + + + + + + + + + + +
    <%= t("admin.polls.index.name") %><%= t("admin.polls.index.status") %> 
    + + <%= link_to "Votación de propuestas 2016", "#" %> + + + Próximamente +
    (15/12/2016 - 15/02/2017) +
    + <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> +
    diff --git a/app/views/admin/poll/polls/new.html.erb b/app/views/admin/poll/polls/new.html.erb index 6e11970d3..b2d74cffc 100644 --- a/app/views/admin/poll/polls/new.html.erb +++ b/app/views/admin/poll/polls/new.html.erb @@ -1 +1,36 @@ -poll new \ No newline at end of file +<%= render 'shared/back_link' %> + +

    <%= t("admin.polls.new.title") %>

    + +
    +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + +
    +
    + +
    \ No newline at end of file diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index a04595e8b..9e267714d 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -9,6 +9,7 @@ en: restore: Restore mark_featured: Featured unmark_featured: Unmark featured + edit: Edit banners: index: title: Banners @@ -153,6 +154,20 @@ en: email_placeholder: Search user by email search: Search user_not_found: User not found + polls: + index: + title: "List of polls" + no_polls: "There are any poll." + create: "Create poll" + name: "Name" + status: "Status" + new: + title: "New poll" + name: "Name" + reference: "Reference number" + open_date: "Open date" + close_date: "Close date" + submit_button: "Create poll" officials: edit: destroy: Remove 'Official' status diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index ba3548215..a711be773 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -9,6 +9,7 @@ es: restore: Volver a mostrar mark_featured: Destacar unmark_featured: Quitar destacado + edit: Editar banners: index: title: Banners @@ -151,6 +152,20 @@ es: email_placeholder: Buscar usuario por email search: Buscar user_not_found: Usuario no encontrado + polls: + index: + title: "Listado de votaciones" + no_polls: "No hay ninguna votación." + create: "Crear votación" + name: "Nombre" + status: "Estado" + new: + title: "Nueva votación" + name: "Nombre" + reference: "Número de referencia" + open_date: "Fecha de apertura" + close_date: "Fecha de cierre" + submit_button: "Crear votación" officials: edit: destroy: Eliminar condición de 'Cargo Público' From 4872c7a4e86985f29a1767b724769fa3bff1d8e8 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 19 Sep 2016 13:36:42 +0200 Subject: [PATCH 06/66] Adds content to edit and show views --- app/views/admin/poll/polls/edit.html.erb | 37 +++++++++++++++++++- app/views/admin/poll/polls/index.html.erb | 6 ++-- app/views/admin/poll/polls/show.html.erb | 42 ++++++++++++++++++++++- config/locales/admin.en.yml | 15 ++++++-- config/locales/admin.es.yml | 13 +++++++ 5 files changed, 106 insertions(+), 7 deletions(-) diff --git a/app/views/admin/poll/polls/edit.html.erb b/app/views/admin/poll/polls/edit.html.erb index ca0a8dc14..68eb7cc3b 100644 --- a/app/views/admin/poll/polls/edit.html.erb +++ b/app/views/admin/poll/polls/edit.html.erb @@ -1 +1,36 @@ -poll edit \ No newline at end of file +<%= render 'shared/back_link' %> + +

    <%= t("admin.polls.edit.title") %>

    + +
    +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + +
    +
    + +
    \ No newline at end of file diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb index 8ba763356..2f7744c97 100644 --- a/app/views/admin/poll/polls/index.html.erb +++ b/app/views/admin/poll/polls/index.html.erb @@ -7,7 +7,7 @@ <%= t("admin.polls.index.no_polls") %> - + @@ -20,7 +20,7 @@ diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb index 61c9d5afb..9b4971214 100644 --- a/app/views/admin/poll/polls/show.html.erb +++ b/app/views/admin/poll/polls/show.html.erb @@ -1 +1,41 @@ -poll show \ No newline at end of file +<%= render "shared/back_link" %> +
    + +

    Votación de propuestas 2016

    +<%= link_to t("admin.actions.edit"), "#", class: "button hollow float-right" %> +

    (REFNUM)

    +

    Próximamente (15/12/2016 - 15/02/2017)

    +<%= link_to t("admin.polls.show.add_booth"), "#", class: "button success" %> + + +
    + <%= t("admin.polls.show.no_booths") %> +
    + + +

    <%= t("admin.polls.show.booths_title") %>

    + +
    - <%= link_to "Votación de propuestas 2016", "#" %> + <%= link_to "Votación de propuestas 2016 (REFNUM)", "3" %> @@ -28,7 +28,7 @@
    (15/12/2016 - 15/02/2017)
    - <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> + <%= link_to t("admin.actions.edit"), "3/edit", class: "button hollow" %>
    + + + + + + + + + + + + + + +
    <%= t("admin.polls.show.name") %><%= t("admin.polls.show.location") %> 
    + + <%= link_to "Urna Moncloa (REFNUM)", "#" %> + + + C/ Isaac Peral, 25. 28003, Madrid + + <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> +
    diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 9e267714d..1141aedf3 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -33,8 +33,6 @@ en: editing: Edit banner form: submit_button: Save changes - errors: - form: errors: form: error: @@ -168,6 +166,19 @@ en: open_date: "Open date" close_date: "Close date" submit_button: "Create poll" + edit: + title: "Edit poll" + name: "Name" + reference: "Reference number" + open_date: "Open date" + close_date: "Close date" + submit_button: "Update poll" + show: + no_booths: "There is no booths in this poll." + add_booth: "Add booth" + booths_title: "List of booths" + name: "Name" + location: "Location" officials: edit: destroy: Remove 'Official' status diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index a711be773..de22029e0 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -166,6 +166,19 @@ es: open_date: "Fecha de apertura" close_date: "Fecha de cierre" submit_button: "Crear votación" + edit: + title: "Editar votación" + name: "Nombre" + reference: "Número de referencia" + open_date: "Fecha de apertura" + close_date: "Fecha de cierre" + submit_button: "Actualizar votación" + show: + no_booths: "No hay urnas en esta votación." + add_booth: "Añadir urna" + booths_title: "Listado de urnas" + name: "Nombre" + location: "Ubicación" officials: edit: destroy: Eliminar condición de 'Cargo Público' From 118d163979f4196fa2f3a09d72e8e112a60b166f Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 17:25:51 +0200 Subject: [PATCH 07/66] hot fix to load last poll on officer's index --- app/views/admin/poll/officers/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/poll/officers/index.html.erb b/app/views/admin/poll/officers/index.html.erb index c330741af..56daabb94 100644 --- a/app/views/admin/poll/officers/index.html.erb +++ b/app/views/admin/poll/officers/index.html.erb @@ -27,7 +27,7 @@ <% if officer.persisted? %> <%= link_to t('admin.poll_officers.officer.delete'), - admin_poll_officer_path(officer), + admin_poll_officer_path(Poll.last, officer), method: :delete, class: "button hollow alert" %> From fcf7920a40d42766076a7e6b197980127940954f Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 19 Sep 2016 17:26:48 +0200 Subject: [PATCH 08/66] Adds booths index content --- app/views/admin/poll/booths/index.html.erb | 45 +++++++++++++++++++++- config/locales/admin.en.yml | 9 +++++ config/locales/admin.es.yml | 9 +++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb index 7ef71767d..3af66c042 100644 --- a/app/views/admin/poll/booths/index.html.erb +++ b/app/views/admin/poll/booths/index.html.erb @@ -1 +1,44 @@ -booth index \ No newline at end of file +

    <%= t("admin.booths.index.title") %>

    + +
    +
    + +
    +
    + +

    <%= t("admin.booths.index.title_list") %>

    + + +
    + <%= t("admin.booths.index.no_booths") %> +
    + + + + + + + + + + + + + + + + + + +
    <%= t("admin.booths.index.name") %><%= t("admin.booths.index.location") %> 
    + + <%= link_to "Urna Moncloa (REFNUM)", "#" %> + + + C/ Isaac Peral, 25. 28003, Madrid + + <%= link_to t("admin.actions.edit"), "/edit", class: "button hollow" %> + <%= link_to t("admin.booths.index.add_officer"), "/edit", class: "button success" %> +
    \ No newline at end of file diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 1141aedf3..4c058992d 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -179,6 +179,15 @@ en: booths_title: "List of booths" name: "Name" location: "Location" + booths: + index: + title: "List of booths" + select_poll: "Select a poll" + title_list: "List of booths of poll %{poll}" + no_booths: "There is no booths in this poll." + name: "Name" + location: "Location" + add_officer: "Add officer" officials: edit: destroy: Remove 'Official' status diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index de22029e0..22fef3006 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -179,6 +179,15 @@ es: booths_title: "Listado de urnas" name: "Nombre" location: "Ubicación" + booths: + index: + title: "Lista de urnas" + select_poll: "Selecciona una votación" + title_list: "Lista de urnas de la votación %{poll}" + no_booths: "No hay urnas en esta votación." + name: "Nombre" + location: "Ubicación" + add_officer: "Añadir presidente" officials: edit: destroy: Eliminar condición de 'Cargo Público' From 5ce886bc6af67131d675a5c5cfa309f0f64aa5fd Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 19 Sep 2016 18:32:21 +0200 Subject: [PATCH 09/66] Add views for admin booths --- app/views/admin/poll/booths/edit.html.erb | 29 ++++++++++++++- app/views/admin/poll/booths/index.html.erb | 9 ++--- app/views/admin/poll/booths/new.html.erb | 29 ++++++++++++++- app/views/admin/poll/booths/show.html.erb | 41 +++++++++++++++++++++- app/views/admin/poll/polls/index.html.erb | 4 +-- config/locales/admin.en.yml | 20 +++++++++++ config/locales/admin.es.yml | 13 +++++++ 7 files changed, 136 insertions(+), 9 deletions(-) diff --git a/app/views/admin/poll/booths/edit.html.erb b/app/views/admin/poll/booths/edit.html.erb index 4f66c61cd..e48db9cdd 100644 --- a/app/views/admin/poll/booths/edit.html.erb +++ b/app/views/admin/poll/booths/edit.html.erb @@ -1 +1,28 @@ -booth edit \ No newline at end of file +<%= render 'shared/back_link' %> + +

    <%= t("admin.booths.edit.title") %>: <%= t("admin.booths.edit.subtitle") %>

    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + "> +
    +
    + +
    +
    + +
    +
    +
    diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb index 3af66c042..2e9a2f70b 100644 --- a/app/views/admin/poll/booths/index.html.erb +++ b/app/views/admin/poll/booths/index.html.erb @@ -14,8 +14,9 @@
    <%= t("admin.booths.index.no_booths") %>
    + - +<%= link_to t("admin.booths.index.add_booth"), new_admin_poll_booth_path, class: "button success" %> @@ -35,10 +36,10 @@ C/ Isaac Peral, 25. 28003, Madrid -
    - <%= link_to t("admin.actions.edit"), "/edit", class: "button hollow" %> - <%= link_to t("admin.booths.index.add_officer"), "/edit", class: "button success" %> + <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> + <%= link_to t("admin.booths.index.add_officer"), "#", class: "button success" %>
    \ No newline at end of file + diff --git a/app/views/admin/poll/booths/new.html.erb b/app/views/admin/poll/booths/new.html.erb index ebcb88bd4..e83d2f47c 100644 --- a/app/views/admin/poll/booths/new.html.erb +++ b/app/views/admin/poll/booths/new.html.erb @@ -1 +1,28 @@ -booth new \ No newline at end of file +<%= render 'shared/back_link' %> + +

    <%= t("admin.booths.new.title") %>: <%= t("admin.booths.new.subtitle") %>

    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + "> +
    +
    + +
    +
    + +
    +
    +
    diff --git a/app/views/admin/poll/booths/show.html.erb b/app/views/admin/poll/booths/show.html.erb index 791a97e48..8a5c2fd99 100644 --- a/app/views/admin/poll/booths/show.html.erb +++ b/app/views/admin/poll/booths/show.html.erb @@ -1 +1,40 @@ -booth show \ No newline at end of file +<%= render 'shared/back_link' %> +
    + +

    Urna Moncloa (REFNUM)

    +<%= link_to t("admin.actions.edit"), "#", class: "button hollow float-right" %> + +

    <%= t("admin.booths.show.location") %>: C/ Isaac Peral, 25. 28003, Madrid

    + +

    <%= t("admin.booths.show.officers_list") %>

    + + +
    + <%= t("admin.booths.show.no_officers") %> +
    + + +<%= link_to t("admin.booths.show.add_officer"), "#", class: "button success" %> + + + <%# @officers.each do |officer| %> + + + + + + <%# end %> +
    + <%# officer.name %> + Admin + + admin@consul.dev + <%# officer.email %> + + <%= link_to t('admin.poll_officers.officer.delete'), "#", class: "button hollow alert" %> + <%# link_to t('admin.poll_officers.officer.delete'), + admin_poll_officer_path(Poll.last, officer), + method: :delete, + class: "button hollow alert" + %> +
    \ No newline at end of file diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb index 2f7744c97..c260ab255 100644 --- a/app/views/admin/poll/polls/index.html.erb +++ b/app/views/admin/poll/polls/index.html.erb @@ -20,7 +20,7 @@ - <%= link_to "Votación de propuestas 2016 (REFNUM)", "3" %> + <%= link_to "Votación de propuestas 2016 (REFNUM)", "polls/3" %> @@ -28,7 +28,7 @@
    (15/12/2016 - 15/02/2017) - <%= link_to t("admin.actions.edit"), "3/edit", class: "button hollow" %> + <%= link_to t("admin.actions.edit"), "polls/3/edit", class: "button hollow" %> diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 4c058992d..40822778f 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -185,9 +185,29 @@ en: select_poll: "Select a poll" title_list: "List of booths of poll %{poll}" no_booths: "There is no booths in this poll." + add_booth: "Add booth" name: "Name" location: "Location" add_officer: "Add officer" + new: + title: "Poll %{poll}" + subtitle: "New booth" + name: "Name" + reference: "Reference number" + location: "Location" + submit_button: "Create booth" + edit: + title: "Poll %{poll}" + subtitle: "Edit booth" + name: "Name" + reference: "Reference number" + location: "Location" + submit_button: "Update booth" + show: + location: "Location" + add_officer: "Add officer" + officers_list: "List of officers" + no_officers: "There is no officers in this booth." officials: edit: destroy: Remove 'Official' status diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 22fef3006..4c807e454 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -185,9 +185,22 @@ es: select_poll: "Selecciona una votación" title_list: "Lista de urnas de la votación %{poll}" no_booths: "No hay urnas en esta votación." + add_booth: "Añadir urna" name: "Nombre" location: "Ubicación" add_officer: "Añadir presidente" + new: + title: "Votación %{poll}" + subtitle: "Nueva urna" + name: "Nombre" + reference: "Número de referencia" + location: "Ubicación" + submit_button: "Crear urna" + show: + location: "Ubicación" + add_officer: "Añadir presidente de mesa" + officers_list: "Lista de presidentes de mesa" + no_officers: "No hay presidentes de mesa en esta urna." officials: edit: destroy: Eliminar condición de 'Cargo Público' From 0ec3a8e8bf2ed9da59096602506c62e31d974cd5 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 13:31:18 +0200 Subject: [PATCH 10/66] validates voter in census --- app/models/poll/voter.rb | 15 ++++++ config/locales/activerecord.en.yml | 4 ++ config/locales/activerecord.es.yml | 4 ++ .../20160914172016_create_poll_voters.rb | 9 ++++ db/schema.rb | 21 ++++++++- lib/census_api.rb | 18 +++++-- spec/factories.rb | 26 ++++++++++ spec/models/poll/voter_spec.rb | 47 +++++++++++++++++++ 8 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 app/models/poll/voter.rb create mode 100644 db/migrate/20160914172016_create_poll_voters.rb create mode 100644 spec/models/poll/voter_spec.rb diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb new file mode 100644 index 000000000..92df28443 --- /dev/null +++ b/app/models/poll/voter.rb @@ -0,0 +1,15 @@ +class Poll + class Voter < ActiveRecord::Base + belongs_to :booth + + validate :in_census + + def in_census + errors.add(:document_number, :not_in_census) unless census_api_response.valid? + end + + def census_api_response + CensusApi.new.call(document_type, document_number) + end + end +end \ No newline at end of file diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 07791e53c..933b0f572 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -82,6 +82,10 @@ en: attributes: max_per_day: invalid: "You have reached the maximum number of private messages per day" + poll/voter: + attributes: + document_number: + not_in_census: "Document not in census" proposal: attributes: tag_list: diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index d5b7f0005..38ceeabdd 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -82,6 +82,10 @@ es: attributes: max_per_day: invalid: "Has llegado al número máximo de mensajes privados por día" + poll/voter: + attributes: + document_number: + not_in_census: "Este documento no aparece en el censo" proposal: attributes: tag_list: diff --git a/db/migrate/20160914172016_create_poll_voters.rb b/db/migrate/20160914172016_create_poll_voters.rb new file mode 100644 index 000000000..df5bb4585 --- /dev/null +++ b/db/migrate/20160914172016_create_poll_voters.rb @@ -0,0 +1,9 @@ +class CreatePollVoters < ActiveRecord::Migration + def change + create_table :poll_voters do |t| + t.integer :booth_id + t.string :document_number + t.string :document_type + end + end +end diff --git a/db/schema.rb b/db/schema.rb index becde4f8a..8a928ca79 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160803154011) do +ActiveRecord::Schema.define(version: 20160914172535) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -270,6 +270,25 @@ ActiveRecord::Schema.define(version: 20160803154011) do add_index "organizations", ["user_id"], name: "index_organizations_on_user_id", using: :btree + create_table "poll_booths", force: :cascade do |t| + t.string "name" + t.integer "poll_id" + end + + create_table "poll_officers", force: :cascade do |t| + t.integer "user_id" + end + + create_table "poll_voters", force: :cascade do |t| + t.integer "booth_id" + t.string "document_number" + t.string "document_type" + end + + create_table "polls", force: :cascade do |t| + t.string "name" + end + create_table "proposal_notifications", force: :cascade do |t| t.string "title" t.text "body" diff --git a/lib/census_api.rb b/lib/census_api.rb index 678a748c6..d80f420e7 100644 --- a/lib/census_api.rb +++ b/lib/census_api.rb @@ -74,7 +74,7 @@ class CensusApi if end_point_available? client.call(:get_habita_datos, message: request(document_type, document_number)).body else - stubbed_response_body + stubbed_response(document_type, document_number) end end @@ -97,8 +97,20 @@ class CensusApi Rails.env.staging? || Rails.env.preproduction? || Rails.env.production? end - def stubbed_response_body - {get_habita_datos_response: {get_habita_datos_return: {hay_errores: false, datos_habitante: { item: {fecha_nacimiento_string: "31-12-1980", identificador_documento: "12345678Z", descripcion_sexo: "Varón" }}, datos_vivienda: {item: {codigo_postal: "28013", codigo_distrito: "01"}}}}} + def stubbed_response(document_type, document_number) + if document_number == "12345678Z" && document_type == "1" + stubbed_valid_response + else + stubbed_invalid_response + end + end + + def stubbed_valid_response + {get_habita_datos_response: {get_habita_datos_return: {datos_habitante: { item: {fecha_nacimiento_string: "31-12-1980", identificador_documento: "12345678Z", descripcion_sexo: "Varón" }}, datos_vivienda: {item: {codigo_postal: "28013", codigo_distrito: "01"}}}}} + end + + def stubbed_invalid_response + {get_habita_datos_response: {get_habita_datos_return: {datos_habitante: {}, datos_vivienda: {}}}} end def is_dni?(document_type) diff --git a/spec/factories.rb b/spec/factories.rb index cdcfe7381..adda53948 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -259,6 +259,32 @@ FactoryGirl.define do user end + factory :poll do + sequence(:name) { |n| "Poll #{n}" } + end + + factory :poll_officer, class: 'Poll::Officer' do + user + end + + factory :poll_booth, class: 'Poll::Booth' do + sequence(:name) { |n| "Booth #{n}" } + poll + end + + factory :poll_voter, class: 'Poll::Voter' do + association :booth, factory: :budget_booth + trait :valid_document do + document_type "1" + document_number "12345678Z" + end + + trait :invalid_document do + document_type "1" + document_number "99999999A" + end + end + factory :organization do user responsible_name "Johnny Utah" diff --git a/spec/models/poll/voter_spec.rb b/spec/models/poll/voter_spec.rb new file mode 100644 index 000000000..de4536243 --- /dev/null +++ b/spec/models/poll/voter_spec.rb @@ -0,0 +1,47 @@ +require 'rails_helper' + +describe :voter do + + let(:poll) { create(:poll) } + let(:booth) { create(:poll_booth, poll: poll) } + + describe "validations" do + + it "should be valid if in census and has not voted" do + voter = build(:poll_voter, :valid_document, booth: booth) + + expect(voter).to be_valid + end + + it "should not be valid if the user is not in the census" do + voter = build(:poll_voter, :invalid_document, booth: booth) + + expect(voter).to_not be_valid + expect(voter.errors.messages[:document_number]).to eq(["Document not in census"]) + end + + it "should not be valid if the user has already voted in the same booth" do + voter1 = create(:poll_voter, :valid_document, booth: booth) + voter2 = build(:poll_voter, :valid_document, booth: booth) + + expect(voter2).to_not be_valid + expect(voter2.errors.messages[:document_number]).to eq(["José García has already voted"]) + end + + it "should not be valid if the user has already voted in another booth" do + booth1 = create(:poll_booth, poll: poll) + booth2 = create(:poll_booth, poll: poll) + + voter1 = create(:poll_voter, :valid_document, booth: booth1) + voter2 = build(:poll_voter, :valid_document, booth: booth2) + + expect(voter2).to_not be_valid + expect(voter2.errors.messages[:document_number]).to eq(["José García has already voted"]) + end + + xit "should not be valid if the user has voted via web" do + pending "Implementation for voting via web" + end + + end +end \ No newline at end of file From 48d2aaa845543346ef01bcb8f6c0e70ffd0a6539 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 18:22:35 +0200 Subject: [PATCH 11/66] validates user has not already voted --- app/models/poll.rb | 4 ++++ app/models/poll/booth.rb | 6 ++++++ app/models/poll/voter.rb | 11 +++++++++++ config/locales/activerecord.en.yml | 1 + config/locales/activerecord.es.yml | 1 + db/migrate/20160914172535_create_poll_booths.rb | 8 ++++++++ 6 files changed, 31 insertions(+) create mode 100644 app/models/poll.rb create mode 100644 app/models/poll/booth.rb create mode 100644 db/migrate/20160914172535_create_poll_booths.rb diff --git a/app/models/poll.rb b/app/models/poll.rb new file mode 100644 index 000000000..507c848aa --- /dev/null +++ b/app/models/poll.rb @@ -0,0 +1,4 @@ +class Poll < ActiveRecord::Base + has_many :booths + has_many :voters, through: :booths, class_name: "Poll::Voter" +end \ No newline at end of file diff --git a/app/models/poll/booth.rb b/app/models/poll/booth.rb new file mode 100644 index 000000000..a05f3d547 --- /dev/null +++ b/app/models/poll/booth.rb @@ -0,0 +1,6 @@ +class Poll + class Booth < ActiveRecord::Base + belongs_to :poll + has_many :voters + end +end \ No newline at end of file diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index 92df28443..353d593b3 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -1,15 +1,26 @@ class Poll class Voter < ActiveRecord::Base belongs_to :booth + delegate :poll, to: :booth validate :in_census + validate :has_not_voted def in_census errors.add(:document_number, :not_in_census) unless census_api_response.valid? end + def has_not_voted + errors.add(:document_number, :has_voted) if has_voted? + end + def census_api_response CensusApi.new.call(document_type, document_number) end + + def has_voted? + poll.voters.where(document_number: document_number, document_type: document_type).present? + end + end end \ No newline at end of file diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 933b0f572..252feb0b5 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -86,6 +86,7 @@ en: attributes: document_number: not_in_census: "Document not in census" + has_voted: "Has already voted" proposal: attributes: tag_list: diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index 38ceeabdd..18faf7900 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -86,6 +86,7 @@ es: attributes: document_number: not_in_census: "Este documento no aparece en el censo" + has_voted: "Ya ha votado" proposal: attributes: tag_list: diff --git a/db/migrate/20160914172535_create_poll_booths.rb b/db/migrate/20160914172535_create_poll_booths.rb new file mode 100644 index 000000000..a474aba49 --- /dev/null +++ b/db/migrate/20160914172535_create_poll_booths.rb @@ -0,0 +1,8 @@ +class CreatePollBooths < ActiveRecord::Migration + def change + create_table :poll_booths do |t| + t.string :name + t.integer :poll_id + end + end +end From 88e7af70d05d9d3490b94b41fd0dbba04c0159c3 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 18:37:37 +0200 Subject: [PATCH 12/66] displays voter name if already voted --- app/models/poll/voter.rb | 8 ++++++-- config/locales/activerecord.en.yml | 2 +- config/locales/activerecord.es.yml | 2 +- lib/census_api.rb | 6 +++++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index 353d593b3..936d8af3b 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -11,16 +11,20 @@ class Poll end def has_not_voted - errors.add(:document_number, :has_voted) if has_voted? + errors.add(:document_number, :has_voted, name: name) if has_voted? end def census_api_response - CensusApi.new.call(document_type, document_number) + @census ||= CensusApi.new.call(document_type, document_number) end def has_voted? poll.voters.where(document_number: document_number, document_type: document_type).present? end + def name + @census.name + end + end end \ No newline at end of file diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 252feb0b5..32f4ef78f 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -86,7 +86,7 @@ en: attributes: document_number: not_in_census: "Document not in census" - has_voted: "Has already voted" + has_voted: "%{name} has already voted" proposal: attributes: tag_list: diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index 18faf7900..a9047df7b 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -86,7 +86,7 @@ es: attributes: document_number: not_in_census: "Este documento no aparece en el censo" - has_voted: "Ya ha votado" + has_voted: "%{name} ya ha votado" proposal: attributes: tag_list: diff --git a/lib/census_api.rb b/lib/census_api.rb index d80f420e7..eadfc549e 100644 --- a/lib/census_api.rb +++ b/lib/census_api.rb @@ -61,6 +61,10 @@ class CensusApi end end + def name + "#{data[:datos_habitante][:item][:nombre]} #{data[:datos_habitante][:item][:apellido1]}" + end + private def data @@ -106,7 +110,7 @@ class CensusApi end def stubbed_valid_response - {get_habita_datos_response: {get_habita_datos_return: {datos_habitante: { item: {fecha_nacimiento_string: "31-12-1980", identificador_documento: "12345678Z", descripcion_sexo: "Varón" }}, datos_vivienda: {item: {codigo_postal: "28013", codigo_distrito: "01"}}}}} + {get_habita_datos_response: {get_habita_datos_return: {datos_habitante: { item: {fecha_nacimiento_string: "31-12-1980", identificador_documento: "12345678Z", descripcion_sexo: "Varón", nombre: "José", apellido1: "García" }}, datos_vivienda: {item: {codigo_postal: "28013", codigo_distrito: "01"}}}}} end def stubbed_invalid_response From 4c08058f80fdd710fa7050ede646d1bc2c0873db Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 18:54:02 +0200 Subject: [PATCH 13/66] updates db schema --- db/schema.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 8a928ca79..e68f466ce 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -275,10 +275,6 @@ ActiveRecord::Schema.define(version: 20160914172535) do t.integer "poll_id" end - create_table "poll_officers", force: :cascade do |t| - t.integer "user_id" - end - create_table "poll_voters", force: :cascade do |t| t.integer "booth_id" t.string "document_number" From 55f4a6bbae019fdd8fd9f497b649e51ac14339c5 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 18:55:16 +0200 Subject: [PATCH 14/66] removes officer factory --- spec/factories.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/factories.rb b/spec/factories.rb index adda53948..48162288d 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -263,10 +263,6 @@ FactoryGirl.define do sequence(:name) { |n| "Poll #{n}" } end - factory :poll_officer, class: 'Poll::Officer' do - user - end - factory :poll_booth, class: 'Poll::Booth' do sequence(:name) { |n| "Booth #{n}" } poll From e0951a2f2d968e76f8d065eb4899cd703d12f110 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Mon, 19 Sep 2016 18:56:10 +0200 Subject: [PATCH 15/66] adds spacing to factories --- spec/factories.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/factories.rb b/spec/factories.rb index 48162288d..cea46a0bc 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -270,6 +270,7 @@ FactoryGirl.define do factory :poll_voter, class: 'Poll::Voter' do association :booth, factory: :budget_booth + trait :valid_document do document_type "1" document_number "12345678Z" From a6384af527126e61c972ce3fe791b7ee4259162e Mon Sep 17 00:00:00 2001 From: rgarcia Date: Tue, 20 Sep 2016 11:44:43 +0200 Subject: [PATCH 16/66] updates query to be more efficient --- app/models/poll/voter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb index 936d8af3b..a517c3f34 100644 --- a/app/models/poll/voter.rb +++ b/app/models/poll/voter.rb @@ -19,7 +19,7 @@ class Poll end def has_voted? - poll.voters.where(document_number: document_number, document_type: document_type).present? + poll.voters.where(document_number: document_number, document_type: document_type).exists? end def name From 7781edf879e8e8595f87bab8d8c9c876a6e166d9 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Tue, 20 Sep 2016 12:32:23 +0200 Subject: [PATCH 17/66] Adds content to booths index and show views --- app/views/admin/poll/booths/index.html.erb | 9 ++++++--- app/views/admin/poll/booths/show.html.erb | 14 ++++++++++++-- config/locales/admin.en.yml | 4 ++-- config/locales/admin.es.yml | 11 +++++++++-- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb index 2e9a2f70b..918479f38 100644 --- a/app/views/admin/poll/booths/index.html.erb +++ b/app/views/admin/poll/booths/index.html.erb @@ -22,6 +22,7 @@ <%= t("admin.booths.index.name") %> <%= t("admin.booths.index.location") %> + <%= t("admin.booths.index.officers") %>   @@ -29,15 +30,17 @@ - <%= link_to "Urna Moncloa (REFNUM)", "#" %> + <%= link_to "Urna Moncloa (REFNUM)", "booths/1" %> C/ Isaac Peral, 25. 28003, Madrid + + N <%= t("admin.booths.index.officers") %> + - <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> - <%= link_to t("admin.booths.index.add_officer"), "#", class: "button success" %> + <%= link_to t("admin.actions.edit"), "booths/1/edit", class: "button hollow" %> diff --git a/app/views/admin/poll/booths/show.html.erb b/app/views/admin/poll/booths/show.html.erb index 8a5c2fd99..34e1a4465 100644 --- a/app/views/admin/poll/booths/show.html.erb +++ b/app/views/admin/poll/booths/show.html.erb @@ -2,7 +2,7 @@

    Urna Moncloa (REFNUM)

    -<%= link_to t("admin.actions.edit"), "#", class: "button hollow float-right" %> +<%= link_to t("admin.actions.edit"), "1/edit", class: "button hollow float-right" %>

    <%= t("admin.booths.show.location") %>: C/ Isaac Peral, 25. 28003, Madrid

    @@ -14,7 +14,17 @@ -<%= link_to t("admin.booths.show.add_officer"), "#", class: "button success" %> +<%= link_to t("admin.booths.show.assign_officer"), "#", class: "button success" %> + +
    + + <%# f.label :valuator_ids, t("admin.spending_proposals.edit.assigned_valuators") %> + + <%# f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> + <%# b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %> + <%# end %> +
    <%# @officers.each do |officer| %> diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 40822778f..40f959a3a 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -188,7 +188,7 @@ en: add_booth: "Add booth" name: "Name" location: "Location" - add_officer: "Add officer" + officers: "Officers" new: title: "Poll %{poll}" subtitle: "New booth" @@ -205,7 +205,7 @@ en: submit_button: "Update booth" show: location: "Location" - add_officer: "Add officer" + assign_officer: "Assign officer" officers_list: "List of officers" no_officers: "There is no officers in this booth." officials: diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 4c807e454..6023da712 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -188,7 +188,7 @@ es: add_booth: "Añadir urna" name: "Nombre" location: "Ubicación" - add_officer: "Añadir presidente" + officers: "Presidentes de mesa" new: title: "Votación %{poll}" subtitle: "Nueva urna" @@ -196,9 +196,16 @@ es: reference: "Número de referencia" location: "Ubicación" submit_button: "Crear urna" + edit: + title: "Votación %{poll}" + subtitle: "Editar urna" + name: "Nombre" + reference: "Número de referencia" + location: "Ubicación" + submit_button: "Actualizar urna" show: location: "Ubicación" - add_officer: "Añadir presidente de mesa" + assign_officer: "Asignar presidente de mesa" officers_list: "Lista de presidentes de mesa" no_officers: "No hay presidentes de mesa en esta urna." officials: From fd220bdf22ab0db91de0af7adae386b00bc59cd0 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Tue, 20 Sep 2016 13:49:48 +0200 Subject: [PATCH 18/66] fixes specs --- spec/features/management/document_verifications_spec.rb | 4 ++-- spec/features/management/email_verifications_spec.rb | 4 ++-- spec/features/management/managed_users_spec.rb | 4 ++-- spec/features/management/users_spec.rb | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/features/management/document_verifications_spec.rb b/spec/features/management/document_verifications_spec.rb index 674349815..130630762 100644 --- a/spec/features/management/document_verifications_spec.rb +++ b/spec/features/management/document_verifications_spec.rb @@ -47,7 +47,7 @@ feature 'DocumentVerifications' do scenario 'Verifying a user which does exists in the census but not in the db redirects allows sending an email' do visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '1234' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to have_content "Please introduce the email used on the account" @@ -66,7 +66,7 @@ feature 'DocumentVerifications' do expect_any_instance_of(Verification::Management::Document).to receive(:under_sixteen?).and_return(true) visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '1234' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to have_content "You must be over 16 to verify your account." diff --git a/spec/features/management/email_verifications_spec.rb b/spec/features/management/email_verifications_spec.rb index 22987f317..d68d9bd5f 100644 --- a/spec/features/management/email_verifications_spec.rb +++ b/spec/features/management/email_verifications_spec.rb @@ -8,7 +8,7 @@ feature 'EmailVerifications' do user = create(:user) visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '1234' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to have_content "Please introduce the email used on the account" @@ -30,7 +30,7 @@ feature 'EmailVerifications' do expect(page).to_not have_link "Verify my account" expect(page).to have_content "Account verified" - expect(user.reload.document_number).to eq('1234') + expect(user.reload.document_number).to eq('12345678Z') expect(user).to be_level_three_verified end diff --git a/spec/features/management/managed_users_spec.rb b/spec/features/management/managed_users_spec.rb index 78010bc39..6ac04b137 100644 --- a/spec/features/management/managed_users_spec.rb +++ b/spec/features/management/managed_users_spec.rb @@ -57,7 +57,7 @@ feature 'Managed User' do user = create(:user) visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '1234' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' within(".account-info") do @@ -88,7 +88,7 @@ feature 'Managed User' do login_as_manager visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '1234' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to have_content "Please introduce the email used on the account" diff --git a/spec/features/management/users_spec.rb b/spec/features/management/users_spec.rb index 1a0618e60..694720cc0 100644 --- a/spec/features/management/users_spec.rb +++ b/spec/features/management/users_spec.rb @@ -9,7 +9,7 @@ feature 'Users' do scenario 'Create a level 3 user from scratch' do visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '1234' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to have_content "Please introduce the email used on the account" @@ -45,10 +45,10 @@ feature 'Users' do end scenario 'Delete a level 2 user account from document verification page', :js do - level_2_user = create(:user, :level_two, document_number: 13579) + level_2_user = create(:user, :level_two, document_number: "12345678Z") visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '13579' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to_not have_content "This user account is already verified." @@ -62,7 +62,7 @@ feature 'Users' do expect(level_2_user.reload.erase_reason).to eq "Deleted by manager: manager_user_#{Manager.last.user_id}" visit management_document_verifications_path - fill_in 'document_verification_document_number', with: '13579' + fill_in 'document_verification_document_number', with: '12345678Z' click_button 'Check' expect(page).to have_content "no user account associated to it" From c965e2dda1526755ad96423442c8f4785e1293b6 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Fri, 23 Sep 2016 09:13:02 +0200 Subject: [PATCH 19/66] tmp commit poll index, show and new --- .../admin/poll/polls_controller.rb | 2 +- app/models/abilities/administrator.rb | 2 + app/views/admin/poll/polls/_poll.html.erb | 16 ++++++++ app/views/admin/poll/polls/index.html.erb | 17 +------- app/views/admin/poll/polls/show.html.erb | 6 ++- spec/features/admin/poll/polls_spec.rb | 40 +++++++++++++++++++ 6 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 app/views/admin/poll/polls/_poll.html.erb create mode 100644 spec/features/admin/poll/polls_spec.rb diff --git a/app/controllers/admin/poll/polls_controller.rb b/app/controllers/admin/poll/polls_controller.rb index b90fd2c11..eb8b417b8 100644 --- a/app/controllers/admin/poll/polls_controller.rb +++ b/app/controllers/admin/poll/polls_controller.rb @@ -1,5 +1,5 @@ class Admin::Poll::PollsController < Admin::BaseController - skip_authorization_check + load_and_authorize_resource def index end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 0f1100137..bd74e1be9 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -40,6 +40,8 @@ module Abilities can [:search, :create, :index, :destroy], ::Manager can [:search, :create, :index, :destroy], ::Poll::Officer + can [:manage], Poll + can :manage, Annotation can [:read, :update, :destroy, :summary], SpendingProposal diff --git a/app/views/admin/poll/polls/_poll.html.erb b/app/views/admin/poll/polls/_poll.html.erb new file mode 100644 index 000000000..a9f2dcd1b --- /dev/null +++ b/app/views/admin/poll/polls/_poll.html.erb @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb index c260ab255..b24cc10f6 100644 --- a/app/views/admin/poll/polls/index.html.erb +++ b/app/views/admin/poll/polls/index.html.erb @@ -16,21 +16,6 @@ - - - - - - - + <%= render @polls %>
    + + <%= link_to poll.name, admin_poll_path(poll) %> + ß + + Próximamente +
    (15/12/2016 - 15/02/2017) +
    + <%= link_to t("admin.actions.edit"), + edit_admin_poll_path(poll), + class: "button hollow" %> +
     
    - - <%= link_to "Votación de propuestas 2016 (REFNUM)", "polls/3" %> - - - Próximamente -
    (15/12/2016 - 15/02/2017) -
    - <%= link_to t("admin.actions.edit"), "polls/3/edit", class: "button hollow" %> -
    diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb index 9b4971214..105cf2fe6 100644 --- a/app/views/admin/poll/polls/show.html.erb +++ b/app/views/admin/poll/polls/show.html.erb @@ -1,8 +1,12 @@ <%= render "shared/back_link" %>
    -

    Votación de propuestas 2016

    +

    + <%= @poll.name %> +

    + <%= link_to t("admin.actions.edit"), "#", class: "button hollow float-right" %> +

    (REFNUM)

    Próximamente (15/12/2016 - 15/02/2017)

    <%= link_to t("admin.polls.show.add_booth"), "#", class: "button success" %> diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb new file mode 100644 index 000000000..a94c81cc9 --- /dev/null +++ b/spec/features/admin/poll/polls_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +feature 'Admin polls' do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + scenario 'Index' do + 3.times { create(:poll) } + + visit admin_root_path + + within('#side_menu') do + click_link "Polls" + end + + expect(page).to have_css ".poll", count: 3 + + Poll.all.each do |poll| + within("#poll_#{poll.id}") do + expect(page).to have_content poll.name +#expect(page).to have_content "Status/Dates" - Hardcoded + end + end + end + + scenario 'Show', :focus do + poll = create(:poll) + + visit admin_polls_path + click_link poll.name + + expect(page).to have_content poll.name +#expect(page).to have_content "Status/Dates" - Hardcoded +#expect(page).to have_content "REFNUM" - Hardcoded + end + +end \ No newline at end of file From 0795da02d8c5d2b44c35ca304c290fc7cd3ad3f4 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 25 Sep 2016 10:20:38 +0200 Subject: [PATCH 20/66] adds poll CRU actions --- .../admin/poll/polls_controller.rb | 22 ++++++++ app/models/poll.rb | 2 + app/views/admin/poll/polls/_form.html.erb | 34 ++++++++++++ app/views/admin/poll/polls/_poll.html.erb | 2 +- app/views/admin/poll/polls/edit.html.erb | 5 +- app/views/admin/poll/polls/index.html.erb | 37 ++++++------- app/views/admin/poll/polls/new.html.erb | 33 +----------- app/views/admin/poll/polls/show.html.erb | 6 +-- config/locales/admin.en.yml | 2 +- config/locales/responders.en.yml | 3 +- config/locales/responders.es.yml | 1 + spec/features/admin/poll/polls_spec.rb | 53 ++++++++++++++++++- spec/models/poll_spec.rb | 16 ++++++ 13 files changed, 157 insertions(+), 59 deletions(-) create mode 100644 app/views/admin/poll/polls/_form.html.erb create mode 100644 spec/models/poll_spec.rb diff --git a/app/controllers/admin/poll/polls_controller.rb b/app/controllers/admin/poll/polls_controller.rb index eb8b417b8..2a7c1e730 100644 --- a/app/controllers/admin/poll/polls_controller.rb +++ b/app/controllers/admin/poll/polls_controller.rb @@ -10,7 +10,29 @@ class Admin::Poll::PollsController < Admin::BaseController def new end + def create + if @poll.save + redirect_to [:admin, @poll], notice: t("flash.actions.create.poll") + else + render :new + end + end + def edit end + def update + if @poll.update(poll_params) + redirect_to [:admin, @poll], notice: t("flash.actions.update.poll") + else + render :edit + end + end + + private + + def poll_params + params.require(:poll).permit(:name) + end + end \ No newline at end of file diff --git a/app/models/poll.rb b/app/models/poll.rb index 507c848aa..4543a2544 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -1,4 +1,6 @@ class Poll < ActiveRecord::Base has_many :booths has_many :voters, through: :booths, class_name: "Poll::Voter" + + validates :name, presence: true end \ No newline at end of file diff --git a/app/views/admin/poll/polls/_form.html.erb b/app/views/admin/poll/polls/_form.html.erb new file mode 100644 index 000000000..64d7177a6 --- /dev/null +++ b/app/views/admin/poll/polls/_form.html.erb @@ -0,0 +1,34 @@ +<%= form_for [:admin, @poll] do |f| %> +
    +
    + <%= f.text_field :name, + placeholder: t('admin.polls.new.name'), + label: t("admin.polls.new.name") %> +
    + +
    + + +
    +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + +
    +
    +<% end %> \ No newline at end of file diff --git a/app/views/admin/poll/polls/_poll.html.erb b/app/views/admin/poll/polls/_poll.html.erb index a9f2dcd1b..4128ad222 100644 --- a/app/views/admin/poll/polls/_poll.html.erb +++ b/app/views/admin/poll/polls/_poll.html.erb @@ -2,7 +2,7 @@ <%= link_to poll.name, admin_poll_path(poll) %> - ß + Próximamente diff --git a/app/views/admin/poll/polls/edit.html.erb b/app/views/admin/poll/polls/edit.html.erb index 68eb7cc3b..0158655a5 100644 --- a/app/views/admin/poll/polls/edit.html.erb +++ b/app/views/admin/poll/polls/edit.html.erb @@ -1,8 +1,9 @@ <%= render 'shared/back_link' %>

    <%= t("admin.polls.edit.title") %>

    +<%= render "form" %> -
    +
    \ No newline at end of file diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb index b24cc10f6..2954e44b8 100644 --- a/app/views/admin/poll/polls/index.html.erb +++ b/app/views/admin/poll/polls/index.html.erb @@ -1,21 +1,22 @@

    <%= t("admin.polls.index.title") %>

    -<%= link_to t("admin.polls.index.create"), new_admin_poll_path, class: "button success float-right" %> +<%= link_to t("admin.polls.index.create"), + new_admin_poll_path, + class: "button success float-right" %> - -
    - <%= t("admin.polls.index.no_polls") %> -
    - - - - - - - - - - - <%= render @polls %> - -
    <%= t("admin.polls.index.name") %><%= t("admin.polls.index.status") %> 
    +<% if Poll.any? %> + + + + + + + + <%= render @polls %> + +
    <%= t("admin.polls.index.name") %><%= t("admin.polls.index.status") %> 
    +<% else %> +
    + <%= t("admin.polls.index.no_polls") %> +
    +<% end %> \ No newline at end of file diff --git a/app/views/admin/poll/polls/new.html.erb b/app/views/admin/poll/polls/new.html.erb index b2d74cffc..ba1ae7260 100644 --- a/app/views/admin/poll/polls/new.html.erb +++ b/app/views/admin/poll/polls/new.html.erb @@ -2,35 +2,4 @@

    <%= t("admin.polls.new.title") %>

    -
    -
    -
    - - -
    - -
    - - -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    - -
    -
    - -
    -
    - -
    \ No newline at end of file +<%= render "form" %> \ No newline at end of file diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb index 105cf2fe6..1b0d1e198 100644 --- a/app/views/admin/poll/polls/show.html.erb +++ b/app/views/admin/poll/polls/show.html.erb @@ -5,7 +5,7 @@ <%= @poll.name %> -<%= link_to t("admin.actions.edit"), "#", class: "button hollow float-right" %> +<%= link_to t("admin.actions.edit"), edit_admin_poll_path(@poll), class: "button hollow float-right" %>

    (REFNUM)

    Próximamente (15/12/2016 - 15/02/2017)

    @@ -26,7 +26,7 @@   - + <%= @poll.booths.each do |booth| %> @@ -40,6 +40,6 @@ <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> - + <% end %> diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 40f959a3a..bb8093b03 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -155,7 +155,7 @@ en: polls: index: title: "List of polls" - no_polls: "There are any poll." + no_polls: "There are no polls." create: "Create poll" name: "Name" status: "Status" diff --git a/config/locales/responders.en.yml b/config/locales/responders.en.yml index ab1641799..422a59e0c 100755 --- a/config/locales/responders.en.yml +++ b/config/locales/responders.en.yml @@ -6,15 +6,16 @@ en: notice: "%{resource_name} created successfully." debate: "Debate created successfully." direct_message: "You message has been sent successfully." + poll: "Poll created successfully." proposal: "Proposal created successfully." proposal_notification: "Your message has been sent correctly." spending_proposal: "Spending proposal created successfully. You can access it from %{activity}" - save_changes: notice: Changes saved update: notice: "%{resource_name} updated successfully." debate: "Debate updated successfully." + poll: "Poll updated successfully." proposal: "Proposal updated successfully." spending_proposal: "Investment project updated succesfully." destroy: diff --git a/config/locales/responders.es.yml b/config/locales/responders.es.yml index 387085d69..c9292b187 100644 --- a/config/locales/responders.es.yml +++ b/config/locales/responders.es.yml @@ -6,6 +6,7 @@ es: notice: "%{resource_name} creado correctamente." debate: "Debate creado correctamente." direct_message: "Tu mensaje ha sido enviado correctamente." + poll: "Votación presencial creada correctamente." proposal: "Propuesta creada correctamente." proposal_notification: "Tu message ha sido enviado correctamente." spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}" diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb index a94c81cc9..8d130e67a 100644 --- a/spec/features/admin/poll/polls_spec.rb +++ b/spec/features/admin/poll/polls_spec.rb @@ -7,6 +7,15 @@ feature 'Admin polls' do login_as(admin.user) end + scenario 'Index empty' do + visit admin_root_path + within('#side_menu') do + click_link "Polls" + end + + expect(page).to have_content "There are no polls" + end + scenario 'Index' do 3.times { create(:poll) } @@ -24,9 +33,10 @@ feature 'Admin polls' do #expect(page).to have_content "Status/Dates" - Hardcoded end end + expect(page).to_not have_content "There are no polls" end - scenario 'Show', :focus do + scenario 'Show' do poll = create(:poll) visit admin_polls_path @@ -37,4 +47,45 @@ feature 'Admin polls' do #expect(page).to have_content "REFNUM" - Hardcoded end + scenario "Create" do + visit admin_polls_path + click_link "Create poll" + + fill_in "poll_name", with: "Upcoming poll" +#fill_in reference_number - Hardcoded +#fill_in open_date - Hardcoded +#fill_in close_date - Hardcoded + click_button "Create poll" + expect(page).to have_content "Poll created successfully" + + expect(page).to have_content "Upcoming poll" + end + + scenario "Edit" do + poll = create(:poll) + + visit admin_poll_path(poll) + click_link "Edit" +save_and_open_page + fill_in "poll_name", with: "Next Poll" +#fill_in reference_number - Hardcoded +#fill_in open_date - Hardcoded +#fill_in close_date - Hardcoded + click_button "Update poll" + expect(page).to have_content "Poll updated successfully" + + expect(page).to have_content "Next Poll" + end + + scenario 'Edit from index' do + poll = create(:poll) + visit admin_polls_path + + within("#poll_#{poll.id}") do + click_link "Edit" + end + + expect(current_path).to eq(edit_admin_poll_path(poll)) + end + end \ No newline at end of file diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb new file mode 100644 index 000000000..7442cdc5a --- /dev/null +++ b/spec/models/poll_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +describe :poll do + + let(:poll) { build(:poll) } + + it "should be valid" do + expect(poll).to be_valid + end + + it "should not be valid without a name" do + poll.name = nil + expect(poll).to_not be_valid + end + +end \ No newline at end of file From 04c58135eec41d72f5554a87bb5dbb6b192e51de Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 25 Sep 2016 10:21:34 +0200 Subject: [PATCH 21/66] adds admin submit button helper --- app/helpers/admin_helper.rb | 4 ++++ spec/helpers/admin_helper_spec.rb | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 spec/helpers/admin_helper_spec.rb diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb index 39ab74b96..f14269fb3 100644 --- a/app/helpers/admin_helper.rb +++ b/app/helpers/admin_helper.rb @@ -16,6 +16,10 @@ module AdminHelper Administrator.all.order('users.username asc').includes(:user).collect { |v| [ v.name, v.id ] } end + def admin_submit_action(resource) + resource.persisted? ? "edit" : "new" + end + private def namespace diff --git a/spec/helpers/admin_helper_spec.rb b/spec/helpers/admin_helper_spec.rb new file mode 100644 index 000000000..0239f1926 --- /dev/null +++ b/spec/helpers/admin_helper_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +describe AdminHelper do + + describe "#admin_submit_action" do + + it "returns new when the the resource has not been persisted" do + poll = build(:poll) + expect(admin_submit_action(poll)).to eq("new") + end + + it "returns edit when the the resource has been persisted" do + poll = create(:poll) + expect(admin_submit_action(poll)).to eq("edit") + end + + end + +end \ No newline at end of file From e2a0b051e91ef76fa9c8657742c29fcef97dd22d Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 25 Sep 2016 10:21:58 +0200 Subject: [PATCH 22/66] allow officers to be created without a poll --- app/controllers/admin/poll/officers_controller.rb | 4 ++-- app/views/admin/_menu.html.erb | 14 ++++++++------ app/views/admin/poll/officers/index.html.erb | 4 ++-- config/routes.rb | 6 +++--- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/controllers/admin/poll/officers_controller.rb b/app/controllers/admin/poll/officers_controller.rb index 7f6f918d7..2641a12b5 100644 --- a/app/controllers/admin/poll/officers_controller.rb +++ b/app/controllers/admin/poll/officers_controller.rb @@ -22,12 +22,12 @@ class Admin::Poll::OfficersController < Admin::BaseController @officer.user_id = params[:user_id] @officer.save - redirect_to admin_poll_officers_path + redirect_to admin_officers_path end def destroy @officer.destroy - redirect_to admin_poll_officers_path + redirect_to admin_officers_path end def show diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 48736c378..0661a3bb6 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -84,7 +84,7 @@
  • > - <%= link_to admin_poll_officers_path(Poll.last) do %> + <%= link_to admin_officers_path do %> <%= t('admin.menu.poll_officers') %> <% end %>
  • @@ -95,11 +95,13 @@ <% end %> -
  • > - <%= link_to admin_poll_booths_url(Poll.last) do %> - <%= t('admin.menu.booths') %> - <% end %> -
  • + <% if Poll.any? %> +
  • > + <%= link_to admin_poll_booths_url(Poll.last) do %> + <%= t('admin.menu.booths') %> + <% end %> +
  • + <% end %>
  • > <%= link_to admin_activity_path do %> diff --git a/app/views/admin/poll/officers/index.html.erb b/app/views/admin/poll/officers/index.html.erb index 56daabb94..cc6393204 100644 --- a/app/views/admin/poll/officers/index.html.erb +++ b/app/views/admin/poll/officers/index.html.erb @@ -1,7 +1,7 @@

    <%= t("admin.poll_officers.index.title") %>

    - <%= form_tag search_admin_poll_officers_path, method: :get, remote: true do %> + <%= form_tag search_admin_officers_path, method: :get, remote: true do %>
    <%= text_field_tag :email, '', placeholder: t('admin.poll_officers.search.email_placeholder') %>
    @@ -27,7 +27,7 @@ <% if officer.persisted? %> <%= link_to t('admin.poll_officers.officer.delete'), - admin_poll_officer_path(Poll.last, officer), + admin_officer_path(officer), method: :delete, class: "button hollow alert" %> diff --git a/config/routes.rb b/config/routes.rb index befbda11e..070823d63 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -178,11 +178,11 @@ Rails.application.routes.draw do end scope module: 'poll' do + resources :officers do + get :search, on: :collection + end resources :polls do resources :booths - resources :officers do - get :search, on: :collection - end end end From a7279d2d67d6a6a7814d9908444adc3313b38bc1 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Sun, 25 Sep 2016 10:26:32 +0200 Subject: [PATCH 23/66] removes poll unused attributes --- app/views/admin/poll/polls/_form.html.erb | 22 ++------------- app/views/admin/poll/polls/edit.html.erb | 34 +---------------------- spec/features/admin/poll/polls_spec.rb | 19 ++++--------- 3 files changed, 8 insertions(+), 67 deletions(-) diff --git a/app/views/admin/poll/polls/_form.html.erb b/app/views/admin/poll/polls/_form.html.erb index 64d7177a6..77961912c 100644 --- a/app/views/admin/poll/polls/_form.html.erb +++ b/app/views/admin/poll/polls/_form.html.erb @@ -5,30 +5,12 @@ placeholder: t('admin.polls.new.name'), label: t("admin.polls.new.name") %>
    - -
    - - -
    - - -
    -
    - - -
    - -
    - - -
    - + <%= f.submit t("admin.polls.#{admin_submit_action(@poll)}.submit_button"), + class: "button success expanded" %>
    <% end %> \ No newline at end of file diff --git a/app/views/admin/poll/polls/edit.html.erb b/app/views/admin/poll/polls/edit.html.erb index 0158655a5..cf131203f 100644 --- a/app/views/admin/poll/polls/edit.html.erb +++ b/app/views/admin/poll/polls/edit.html.erb @@ -1,37 +1,5 @@ <%= render 'shared/back_link' %>

    <%= t("admin.polls.edit.title") %>

    -<%= render "form" %> - - - \ No newline at end of file +<%= render "form" %> \ No newline at end of file diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb index 8d130e67a..bab7b5847 100644 --- a/spec/features/admin/poll/polls_spec.rb +++ b/spec/features/admin/poll/polls_spec.rb @@ -30,7 +30,6 @@ feature 'Admin polls' do Poll.all.each do |poll| within("#poll_#{poll.id}") do expect(page).to have_content poll.name -#expect(page).to have_content "Status/Dates" - Hardcoded end end expect(page).to_not have_content "There are no polls" @@ -43,8 +42,6 @@ feature 'Admin polls' do click_link poll.name expect(page).to have_content poll.name -#expect(page).to have_content "Status/Dates" - Hardcoded -#expect(page).to have_content "REFNUM" - Hardcoded end scenario "Create" do @@ -52,12 +49,9 @@ feature 'Admin polls' do click_link "Create poll" fill_in "poll_name", with: "Upcoming poll" -#fill_in reference_number - Hardcoded -#fill_in open_date - Hardcoded -#fill_in close_date - Hardcoded click_button "Create poll" - expect(page).to have_content "Poll created successfully" + expect(page).to have_content "Poll created successfully" expect(page).to have_content "Upcoming poll" end @@ -66,14 +60,11 @@ feature 'Admin polls' do visit admin_poll_path(poll) click_link "Edit" -save_and_open_page - fill_in "poll_name", with: "Next Poll" -#fill_in reference_number - Hardcoded -#fill_in open_date - Hardcoded -#fill_in close_date - Hardcoded - click_button "Update poll" - expect(page).to have_content "Poll updated successfully" + fill_in "poll_name", with: "Next Poll" + click_button "Update poll" + + expect(page).to have_content "Poll updated successfully" expect(page).to have_content "Next Poll" end From 042cb14dbdbf198d65e825d9c0310d41f07a795a Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 11:53:46 +0200 Subject: [PATCH 24/66] moves poll spec to poll folder --- spec/models/{ => poll}/poll_spec.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/models/{ => poll}/poll_spec.rb (100%) diff --git a/spec/models/poll_spec.rb b/spec/models/poll/poll_spec.rb similarity index 100% rename from spec/models/poll_spec.rb rename to spec/models/poll/poll_spec.rb From f3ad806c8b1433eda70c5076f8cea89f99e20c44 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 11:54:29 +0200 Subject: [PATCH 25/66] updates dev seeds with booths --- db/dev_seeds.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index beb1d815f..2fe812ea5 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -341,4 +341,8 @@ puts "Creating polls" 3.times.each_with_index do |i| Poll.create(name: "Poll #{i}") +end + +10.times.each_with_index do |i| + Poll::Booth.create(name: "Booth #{i}", poll: Poll.all.sample) end \ No newline at end of file From 7db3683c27f1b6f9a56a2b1429463fca80d98b64 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 11:55:11 +0200 Subject: [PATCH 26/66] adds consistency to syntax --- app/views/admin/poll/polls/index.html.erb | 2 +- config/routes.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/poll/polls/index.html.erb b/app/views/admin/poll/polls/index.html.erb index 2954e44b8..b4c18d21b 100644 --- a/app/views/admin/poll/polls/index.html.erb +++ b/app/views/admin/poll/polls/index.html.erb @@ -4,7 +4,7 @@ new_admin_poll_path, class: "button success float-right" %> -<% if Poll.any? %> +<% if @polls.any? %> diff --git a/config/routes.rb b/config/routes.rb index 070823d63..f682ab529 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -177,7 +177,7 @@ Rails.application.routes.draw do get :search, on: :collection end - scope module: 'poll' do + scope module: :poll do resources :officers do get :search, on: :collection end From 2c3127b6bd74916420cb70e30f39b3e0bf879a9c Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 11:56:19 +0200 Subject: [PATCH 27/66] adds booth backend for index, show, create and edit actions --- .../admin/poll/booths_controller.rb | 31 +++- app/models/abilities/administrator.rb | 5 +- app/models/poll/booth.rb | 2 + app/views/admin/poll/booths/_form.html.erb | 20 +++ app/views/admin/poll/booths/edit.html.erb | 29 +--- app/views/admin/poll/booths/index.html.erb | 49 +++--- app/views/admin/poll/booths/new.html.erb | 29 +--- app/views/admin/poll/booths/show.html.erb | 13 +- app/views/admin/poll/polls/show.html.erb | 4 +- config/locales/admin.en.yml | 4 +- config/locales/responders.en.yml | 2 + config/locales/responders.es.yml | 3 + .../20160926090107_add_location_to_booths.rb | 5 + db/schema.rb | 11 +- spec/factories.rb | 1 + spec/features/admin/poll/booths_spec.rb | 146 ++++++++++++++++++ spec/models/abilities/administrator_spec.rb | 3 + spec/models/poll/booth_spec.rb | 16 ++ 18 files changed, 288 insertions(+), 85 deletions(-) create mode 100644 app/views/admin/poll/booths/_form.html.erb create mode 100644 db/migrate/20160926090107_add_location_to_booths.rb create mode 100644 spec/features/admin/poll/booths_spec.rb create mode 100644 spec/models/poll/booth_spec.rb diff --git a/app/controllers/admin/poll/booths_controller.rb b/app/controllers/admin/poll/booths_controller.rb index 9b1e62f8f..95057ce2f 100644 --- a/app/controllers/admin/poll/booths_controller.rb +++ b/app/controllers/admin/poll/booths_controller.rb @@ -1,5 +1,8 @@ class Admin::Poll::BoothsController < Admin::BaseController - skip_authorization_check + load_and_authorize_resource :poll + load_and_authorize_resource class: 'Poll::Booth', through: :poll + + before_action :load_polls, only: :index def index end @@ -10,7 +13,33 @@ class Admin::Poll::BoothsController < Admin::BaseController def new end + def create + if @booth.save + redirect_to admin_poll_booth_path(@poll, @booth), notice: t("flash.actions.create.poll_booth") + else + render :new + end + end + def edit end + def update + if @booth.update(booth_params) + redirect_to admin_poll_booth_path(@poll, @booth), notice: t("flash.actions.update.poll_booth") + else + render :edit + end + end + + private + + def booth_params + params.require(:poll_booth).permit(:name, :location) + end + + def load_polls + @polls = Poll.all + end + end \ No newline at end of file diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index bd74e1be9..a0e040ab3 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -40,12 +40,13 @@ module Abilities can [:search, :create, :index, :destroy], ::Manager can [:search, :create, :index, :destroy], ::Poll::Officer - can [:manage], Poll - can :manage, Annotation can [:read, :update, :destroy, :summary], SpendingProposal can [:search, :edit, :update, :create, :index, :destroy], Banner + + can [:manage], Poll + can [:manage], Poll::Booth end end end diff --git a/app/models/poll/booth.rb b/app/models/poll/booth.rb index a05f3d547..eb7d81b8c 100644 --- a/app/models/poll/booth.rb +++ b/app/models/poll/booth.rb @@ -2,5 +2,7 @@ class Poll class Booth < ActiveRecord::Base belongs_to :poll has_many :voters + + validates :name, presence: true end end \ No newline at end of file diff --git a/app/views/admin/poll/booths/_form.html.erb b/app/views/admin/poll/booths/_form.html.erb new file mode 100644 index 000000000..31d60c0f0 --- /dev/null +++ b/app/views/admin/poll/booths/_form.html.erb @@ -0,0 +1,20 @@ +
    +
    + <%= f.text_field :name, + placeholder: t('admin.booths.new.name'), + label: t("admin.booths.new.name") %> +
    + +
    + <%= f.text_field :location, + placeholder: t("admin.booths.new.location"), + label: t("admin.booths.new.location") %> +
    +
    + +
    +
    + <%= f.submit t("admin.booths.#{admin_submit_action(@booth)}.submit_button"), + class: "button success expanded" %> +
    +
    \ No newline at end of file diff --git a/app/views/admin/poll/booths/edit.html.erb b/app/views/admin/poll/booths/edit.html.erb index e48db9cdd..23d825b91 100644 --- a/app/views/admin/poll/booths/edit.html.erb +++ b/app/views/admin/poll/booths/edit.html.erb @@ -1,28 +1,7 @@ <%= render 'shared/back_link' %> -

    <%= t("admin.booths.edit.title") %>: <%= t("admin.booths.edit.subtitle") %>

    +

    <%= t("admin.booths.edit.title", poll: @poll.name) %>: <%= t("admin.booths.edit.subtitle") %>

    -
    -
    -
    - - -
    - -
    - - -
    - -
    - - "> -
    -
    - -
    -
    - -
    -
    - +<%= form_for @booth, url: admin_poll_booth_path(@poll, @booth) do |f| %> + <%= render "form", f: f %> +<% end %> diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb index 918479f38..b3733670d 100644 --- a/app/views/admin/poll/booths/index.html.erb +++ b/app/views/admin/poll/booths/index.html.erb @@ -1,22 +1,27 @@

    <%= t("admin.booths.index.title") %>

    -
    -
    - -
    - - -

    <%= t("admin.booths.index.title_list") %>

    - - -
    - <%= t("admin.booths.index.no_booths") %> +
    + <%= form_tag '', method: :get do %> + <%= select_tag "poll_id", + options_for_select(@polls.collect {|poll| + [poll.name, admin_poll_booths_path(poll)] + }), + prompt: t("admin.booths.index.select_poll"), + class: "js-location-changer" %> + <% end %>
    - -<%= link_to t("admin.booths.index.add_booth"), new_admin_poll_booth_path, class: "button success" %> +

    <%= t("admin.booths.index.title_list", poll: @poll.name) %>

    + +<% if @booths.empty? %> +
    + <%= t("admin.booths.index.no_booths") %> +
    +<% end %> + +<%= link_to t("admin.booths.index.add_booth"), + new_admin_poll_booth_path, + class: "button success" %>
    <%= t("admin.polls.index.name") %>
    @@ -26,23 +31,25 @@ - - + <% @booths.each do |booth| %> + - + <% end %>
     
    - <%= link_to "Urna Moncloa (REFNUM)", "booths/1" %> + <%= link_to booth.name, admin_poll_booth_path(@poll, booth) %> - C/ Isaac Peral, 25. 28003, Madrid + <%= booth.location %> N <%= t("admin.booths.index.officers") %> - <%= link_to t("admin.actions.edit"), "booths/1/edit", class: "button hollow" %> + <%= link_to t("admin.actions.edit"), + edit_admin_poll_booth_path(@poll, booth), + class: "button hollow" %>
    diff --git a/app/views/admin/poll/booths/new.html.erb b/app/views/admin/poll/booths/new.html.erb index e83d2f47c..cffcfab72 100644 --- a/app/views/admin/poll/booths/new.html.erb +++ b/app/views/admin/poll/booths/new.html.erb @@ -1,28 +1,7 @@ <%= render 'shared/back_link' %> -

    <%= t("admin.booths.new.title") %>: <%= t("admin.booths.new.subtitle") %>

    +

    <%= t("admin.booths.new.title", poll: @poll.name) %>: <%= t("admin.booths.new.subtitle") %>

    -
    -
    -
    - - -
    - -
    - - -
    - -
    - - "> -
    -
    - -
    -
    - -
    -
    -
    +<%= form_for @booth, url: admin_poll_booths_path(@poll) do |f| %> + <%= render "form", f: f %> +<% end %> \ No newline at end of file diff --git a/app/views/admin/poll/booths/show.html.erb b/app/views/admin/poll/booths/show.html.erb index 34e1a4465..55f7d5504 100644 --- a/app/views/admin/poll/booths/show.html.erb +++ b/app/views/admin/poll/booths/show.html.erb @@ -1,10 +1,17 @@ <%= render 'shared/back_link' %>
    -

    Urna Moncloa (REFNUM)

    -<%= link_to t("admin.actions.edit"), "1/edit", class: "button hollow float-right" %> +

    + <%= @booth.name %> +

    +<%= link_to t("admin.actions.edit"), + edit_admin_poll_booth_path(@poll, @booth), + class: "button hollow float-right" %> -

    <%= t("admin.booths.show.location") %>: C/ Isaac Peral, 25. 28003, Madrid

    +

    + <%= t("admin.booths.show.location") %>: + <%= @booth.location %> +

    <%= t("admin.booths.show.officers_list") %>

    diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb index 1b0d1e198..17248d4b9 100644 --- a/app/views/admin/poll/polls/show.html.erb +++ b/app/views/admin/poll/polls/show.html.erb @@ -5,7 +5,9 @@ <%= @poll.name %> -<%= link_to t("admin.actions.edit"), edit_admin_poll_path(@poll), class: "button hollow float-right" %> +<%= link_to t("admin.actions.edit"), + edit_admin_poll_path(@poll), + class: "button hollow float-right" %>

    (REFNUM)

    Próximamente (15/12/2016 - 15/02/2017)

    diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index bb8093b03..db4cf34ca 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -174,7 +174,7 @@ en: close_date: "Close date" submit_button: "Update poll" show: - no_booths: "There is no booths in this poll." + no_booths: "There are no booths in this poll." add_booth: "Add booth" booths_title: "List of booths" name: "Name" @@ -184,7 +184,7 @@ en: title: "List of booths" select_poll: "Select a poll" title_list: "List of booths of poll %{poll}" - no_booths: "There is no booths in this poll." + no_booths: "There are no booths in this poll." add_booth: "Add booth" name: "Name" location: "Location" diff --git a/config/locales/responders.en.yml b/config/locales/responders.en.yml index 422a59e0c..68d77b0d2 100755 --- a/config/locales/responders.en.yml +++ b/config/locales/responders.en.yml @@ -7,6 +7,7 @@ en: debate: "Debate created successfully." direct_message: "You message has been sent successfully." poll: "Poll created successfully." + poll_booth: "Booth created successfully." proposal: "Proposal created successfully." proposal_notification: "Your message has been sent correctly." spending_proposal: "Spending proposal created successfully. You can access it from %{activity}" @@ -16,6 +17,7 @@ en: notice: "%{resource_name} updated successfully." debate: "Debate updated successfully." poll: "Poll updated successfully." + poll_booth: "Booth updated successfully." proposal: "Proposal updated successfully." spending_proposal: "Investment project updated succesfully." destroy: diff --git a/config/locales/responders.es.yml b/config/locales/responders.es.yml index c9292b187..105b00903 100644 --- a/config/locales/responders.es.yml +++ b/config/locales/responders.es.yml @@ -7,6 +7,7 @@ es: debate: "Debate creado correctamente." direct_message: "Tu mensaje ha sido enviado correctamente." poll: "Votación presencial creada correctamente." + poll_booth: "Urna creada correctamente." proposal: "Propuesta creada correctamente." proposal_notification: "Tu message ha sido enviado correctamente." spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}" @@ -16,6 +17,8 @@ es: notice: "%{resource_name} actualizado correctamente." debate: "Debate actualizado correctamente." proposal: "Propuesta actualizada correctamente." + poll: "Votación presencial actualizada correctamente." + poll_booth: "Urna actualizada correctamente." spending_proposal: "Propuesta de inversión actualizada correctamente." destroy: spending_proposal: "Propuesta de inversión eliminada." \ No newline at end of file diff --git a/db/migrate/20160926090107_add_location_to_booths.rb b/db/migrate/20160926090107_add_location_to_booths.rb new file mode 100644 index 000000000..146f55d41 --- /dev/null +++ b/db/migrate/20160926090107_add_location_to_booths.rb @@ -0,0 +1,5 @@ +class AddLocationToBooths < ActiveRecord::Migration + def change + add_column :poll_booths, :location, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 205fc5f21..493dfbe3a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160914172535) do +ActiveRecord::Schema.define(version: 20160926090107) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -273,6 +273,11 @@ ActiveRecord::Schema.define(version: 20160914172535) do create_table "poll_booths", force: :cascade do |t| t.string "name" t.integer "poll_id" + t.string "location" + end + + create_table "poll_officers", force: :cascade do |t| + t.integer "user_id" end create_table "poll_voters", force: :cascade do |t| @@ -281,10 +286,6 @@ ActiveRecord::Schema.define(version: 20160914172535) do t.string "document_type" end - create_table "poll_officers", force: :cascade do |t| - t.integer "user_id" - end - create_table "polls", force: :cascade do |t| t.string "name" end diff --git a/spec/factories.rb b/spec/factories.rb index ac7bb379b..f7e09b7e8 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -269,6 +269,7 @@ FactoryGirl.define do factory :poll_booth, class: 'Poll::Booth' do sequence(:name) { |n| "Booth #{n}" } + sequence(:location) { |n| "Street #{n}" } poll end diff --git a/spec/features/admin/poll/booths_spec.rb b/spec/features/admin/poll/booths_spec.rb new file mode 100644 index 000000000..ad46c67fb --- /dev/null +++ b/spec/features/admin/poll/booths_spec.rb @@ -0,0 +1,146 @@ +require 'rails_helper' + +feature 'Admin booths' do + + let!(:poll) { create(:poll) } + + background do + admin = create(:administrator) + login_as(admin.user) + end + + scenario 'Index empty' do + visit admin_root_path + + within('#side_menu') do + click_link "Booths" + end + + expect(page).to have_content "There are no booths in this poll" + end + + scenario 'No link to booths when no polls' do + Poll.destroy_all + + visit admin_root_path + + within('#side_menu') do + expect(page).to_not have_link "Booths" + end + end + + scenario 'Index' do + 3.times { create(:poll_booth, poll: poll) } + + visit admin_root_path + + within('#side_menu') do + click_link "Booths" + end + + expect(page).to have_css ".booth", count: 3 + + booths = Poll::Booth.all + booths.each do |booth| + within("#booth_#{booth.id}") do + expect(page).to have_content booth.name + expect(page).to have_content booth.location + end + end + expect(page).to_not have_content "There are no booths" + end + + scenario "Index default to last poll" do + poll1 = create(:poll) + poll2 = create(:poll) + + booth1 = create(:poll_booth, poll: poll1) + booth2 = create(:poll_booth, poll: poll2) + + visit admin_root_path + + within('#side_menu') do + click_link "Booths" + end + + expect(page).to have_css ".booth", count: 1 + expect(page).to have_content booth2.name + expect(page).to_not have_content booth1.name + end + + scenario "Index select poll", :js do + poll1 = create(:poll) + poll2 = create(:poll) + + booth1 = create(:poll_booth, poll: poll1) + booth2 = create(:poll_booth, poll: poll2) + + visit admin_root_path + + within('#side_menu') do + click_link "Booths" + end + + select poll1.name, from: "poll_id" + + expect(page).to have_content "List of booths of poll #{poll1.name}" + expect(page).to have_css ".booth", count: 1 + expect(page).to have_content booth1.name + expect(page).to_not have_content booth2.name + end + + scenario 'Show' do + booth = create(:poll_booth, poll: poll) + + visit admin_poll_booths_path(poll) + click_link booth.name + + expect(page).to have_content booth.name + expect(page).to have_content booth.location + end + + scenario "Create" do + visit admin_poll_booths_path(poll) + click_link "Add booth" + + expect(page).to have_content "Poll #{poll.name}" + + fill_in "poll_booth_name", with: "Upcoming booth" + fill_in "poll_booth_location", with: "39th Street, number 2, ground floor" + click_button "Create booth" + + expect(page).to have_content "Booth created successfully" + expect(page).to have_content "Upcoming booth" + expect(page).to have_content "39th Street, number 2, ground floor" + end + + scenario "Edit" do + booth = create(:poll_booth, poll: poll) + + visit admin_poll_booths_path(poll) + + click_link "Edit" + + expect(page).to have_content "Poll #{poll.name}" + + fill_in "poll_booth_name", with: "Next booth" + fill_in "poll_booth_location", with: "40th Street, number 1, firts floor" + click_button "Update booth" + + expect(page).to have_content "Booth updated successfully" + expect(page).to have_content "Next booth" + expect(page).to have_content "40th Street, number 1, firts floor" + end + + scenario 'Edit from index' do + booth = create(:poll_booth, poll: poll) + visit admin_poll_booths_path(poll) + + within("#booth_#{booth.id}") do + click_link "Edit" + end + + expect(current_path).to eq(edit_admin_poll_booth_path(poll, booth)) + end + +end \ No newline at end of file diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb index f9ed7a0c5..04fd199f0 100644 --- a/spec/models/abilities/administrator_spec.rb +++ b/spec/models/abilities/administrator_spec.rb @@ -56,4 +56,7 @@ describe "Abilities::Administrator" do it { should be_able_to(:update, SpendingProposal) } it { should be_able_to(:valuate, SpendingProposal) } it { should be_able_to(:destroy, SpendingProposal) } + + it { should be_able_to(:manage, Poll) } + it { should be_able_to(:manage, Poll::Booth) } end diff --git a/spec/models/poll/booth_spec.rb b/spec/models/poll/booth_spec.rb new file mode 100644 index 000000000..2fabb9c12 --- /dev/null +++ b/spec/models/poll/booth_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +describe :booth do + + let(:booth) { build(:poll_booth) } + + it "should be valid" do + expect(booth).to be_valid + end + + it "should not be valid without a name" do + booth.name = nil + expect(booth).to_not be_valid + end + +end \ No newline at end of file From a8ea86fae1f84f7ff39a542146b3609ec8eb6e7f Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 11:56:48 +0200 Subject: [PATCH 28/66] removes unused attributes from poll show --- app/views/admin/poll/polls/_poll.html.erb | 4 ---- app/views/admin/poll/polls/show.html.erb | 2 -- 2 files changed, 6 deletions(-) diff --git a/app/views/admin/poll/polls/_poll.html.erb b/app/views/admin/poll/polls/_poll.html.erb index 4128ad222..d90fed14a 100644 --- a/app/views/admin/poll/polls/_poll.html.erb +++ b/app/views/admin/poll/polls/_poll.html.erb @@ -4,10 +4,6 @@ <%= link_to poll.name, admin_poll_path(poll) %>
    - - Próximamente -
    (15/12/2016 - 15/02/2017) - <%= link_to t("admin.actions.edit"), edit_admin_poll_path(poll), diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb index 17248d4b9..8a02ebfd7 100644 --- a/app/views/admin/poll/polls/show.html.erb +++ b/app/views/admin/poll/polls/show.html.erb @@ -9,8 +9,6 @@ edit_admin_poll_path(@poll), class: "button hollow float-right" %> -

    (REFNUM)

    -

    Próximamente (15/12/2016 - 15/02/2017)

    <%= link_to t("admin.polls.show.add_booth"), "#", class: "button success" %> From e97e7e20dc27339ea932ff148ce59022ab72ca44 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 12:01:58 +0200 Subject: [PATCH 29/66] maintains poll date and status in index for demo --- app/views/admin/poll/polls/_poll.html.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/views/admin/poll/polls/_poll.html.erb b/app/views/admin/poll/polls/_poll.html.erb index d90fed14a..4128ad222 100644 --- a/app/views/admin/poll/polls/_poll.html.erb +++ b/app/views/admin/poll/polls/_poll.html.erb @@ -4,6 +4,10 @@ <%= link_to poll.name, admin_poll_path(poll) %> + + Próximamente +
    (15/12/2016 - 15/02/2017) + <%= link_to t("admin.actions.edit"), edit_admin_poll_path(poll), From 6387d281578bd00cd7b9f10a5e10ec3cd8379910 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 12:34:24 +0200 Subject: [PATCH 30/66] adds booth info to poll show --- app/views/admin/poll/booths/_booth.html.erb | 18 +++++++ app/views/admin/poll/booths/index.html.erb | 21 +------- app/views/admin/poll/polls/show.html.erb | 55 +++++++++------------ config/locales/admin.en.yml | 1 + config/locales/admin.es.yml | 1 + spec/features/admin/poll/polls_spec.rb | 44 ++++++++++++++++- 6 files changed, 88 insertions(+), 52 deletions(-) create mode 100644 app/views/admin/poll/booths/_booth.html.erb diff --git a/app/views/admin/poll/booths/_booth.html.erb b/app/views/admin/poll/booths/_booth.html.erb new file mode 100644 index 000000000..ff1683867 --- /dev/null +++ b/app/views/admin/poll/booths/_booth.html.erb @@ -0,0 +1,18 @@ + + + + <%= link_to booth.name, admin_poll_booth_path(@poll, booth) %> + + + + <%= booth.location %> + + + N <%= t("admin.booths.index.officers") %> + + + <%= link_to t("admin.actions.edit"), + edit_admin_poll_booth_path(@poll, booth), + class: "button hollow" %> + + \ No newline at end of file diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb index b3733670d..d2a9a7e5a 100644 --- a/app/views/admin/poll/booths/index.html.erb +++ b/app/views/admin/poll/booths/index.html.erb @@ -20,7 +20,7 @@ <% end %> <%= link_to t("admin.booths.index.add_booth"), - new_admin_poll_booth_path, + new_admin_poll_booth_path(@poll), class: "button success" %> @@ -32,24 +32,7 @@ <% @booths.each do |booth| %> - - - - - - + <%= render partial: "booth", locals: { booth: booth } %> <% end %>
    - - <%= link_to booth.name, admin_poll_booth_path(@poll, booth) %> - - - <%= booth.location %> - - N <%= t("admin.booths.index.officers") %> - - <%= link_to t("admin.actions.edit"), - edit_admin_poll_booth_path(@poll, booth), - class: "button hollow" %> -
    diff --git a/app/views/admin/poll/polls/show.html.erb b/app/views/admin/poll/polls/show.html.erb index 8a02ebfd7..bed01af41 100644 --- a/app/views/admin/poll/polls/show.html.erb +++ b/app/views/admin/poll/polls/show.html.erb @@ -9,37 +9,28 @@ edit_admin_poll_path(@poll), class: "button hollow float-right" %> -<%= link_to t("admin.polls.show.add_booth"), "#", class: "button success" %> +<%= link_to t("admin.polls.show.add_booth"), + new_admin_poll_booth_path(@poll), + class: "button success" %> - -
    - <%= t("admin.polls.show.no_booths") %> -
    - +<% if @poll.booths.empty? %> +
    + <%= t("admin.polls.show.no_booths") %> +
    +<% else %> +

    <%= t("admin.polls.show.booths_title") %>

    -

    <%= t("admin.polls.show.booths_title") %>

    - - - - - - - - - <%= @poll.booths.each do |booth| %> - - - - - - <% end %> - -
    <%= t("admin.polls.show.name") %><%= t("admin.polls.show.location") %> 
    - - <%= link_to "Urna Moncloa (REFNUM)", "#" %> - - - C/ Isaac Peral, 25. 28003, Madrid - - <%= link_to t("admin.actions.edit"), "#", class: "button hollow" %> -
    + + + + + + + + + <% @poll.booths.each do |booth| %> + <%= render partial: "admin/poll/booths/booth", locals: { booth: booth } %> + <% end %> + +
    <%= t("admin.polls.show.name") %><%= t("admin.polls.show.location") %><%= t("admin.polls.show.officers") %> 
    +<% end %> \ No newline at end of file diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index db4cf34ca..ef294262d 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -179,6 +179,7 @@ en: booths_title: "List of booths" name: "Name" location: "Location" + officers: "Officers" booths: index: title: "List of booths" diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 6023da712..48dfe2959 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -179,6 +179,7 @@ es: booths_title: "Listado de urnas" name: "Nombre" location: "Ubicación" + officers: "Presidentes de mesa" booths: index: title: "Lista de urnas" diff --git a/spec/features/admin/poll/polls_spec.rb b/spec/features/admin/poll/polls_spec.rb index bab7b5847..80f875567 100644 --- a/spec/features/admin/poll/polls_spec.rb +++ b/spec/features/admin/poll/polls_spec.rb @@ -27,7 +27,8 @@ feature 'Admin polls' do expect(page).to have_css ".poll", count: 3 - Poll.all.each do |poll| + polls = Poll.all + polls.each do |poll| within("#poll_#{poll.id}") do expect(page).to have_content poll.name end @@ -79,4 +80,45 @@ feature 'Admin polls' do expect(current_path).to eq(edit_admin_poll_path(poll)) end + context "Booths" do + + context "Poll show" do + + scenario "No booths" do + poll = create(:poll) + visit admin_poll_path(poll) + + expect(page).to have_content "There are no booths in this poll." + end + + scenario "Booth list" do + poll = create(:poll) + 3.times { create(:poll_booth, poll: poll) } + + visit admin_poll_path(poll) + + expect(page).to have_css ".booth", count: 3 + + booths = Poll::Booth.all + booths.each do |booth| + within("#booth_#{booth.id}") do + expect(page).to have_content booth.name + expect(page).to have_content booth.location + end + end + expect(page).to_not have_content "There are no booths" + end + + scenario "Add booth" do + poll = create(:poll) + visit admin_poll_path(poll) + + click_link "Add booth" + + expect(current_path).to eq(new_admin_poll_booth_path(poll)) + expect(page).to have_content poll.name + end + end + end + end \ No newline at end of file From 527b734e0ebae60f30c76e03e7a5082eacdad0a4 Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 28 Sep 2016 18:39:01 +0200 Subject: [PATCH 31/66] assigns officers to booths --- .../admin/poll/booths_controller.rb | 3 +- app/helpers/officers_helper.rb | 7 + app/models/poll/booth.rb | 2 + app/models/poll/officing_booth.rb | 6 + app/views/admin/poll/booths/show.html.erb | 40 +++--- config/locales/admin.en.yml | 2 +- .../20160928113143_create_officing_booths.rb | 9 ++ db/schema.rb | 9 +- spec/factories.rb | 5 + spec/features/admin/poll/officers_spec.rb | 129 +++++++++++++++++- 10 files changed, 185 insertions(+), 27 deletions(-) create mode 100644 app/helpers/officers_helper.rb create mode 100644 app/models/poll/officing_booth.rb create mode 100644 db/migrate/20160928113143_create_officing_booths.rb diff --git a/app/controllers/admin/poll/booths_controller.rb b/app/controllers/admin/poll/booths_controller.rb index 95057ce2f..1d05ddab5 100644 --- a/app/controllers/admin/poll/booths_controller.rb +++ b/app/controllers/admin/poll/booths_controller.rb @@ -8,6 +8,7 @@ class Admin::Poll::BoothsController < Admin::BaseController end def show + @officers = Poll::Officer.all end def new @@ -35,7 +36,7 @@ class Admin::Poll::BoothsController < Admin::BaseController private def booth_params - params.require(:poll_booth).permit(:name, :location) + params.require(:poll_booth).permit(:name, :location, officer_ids: []) end def load_polls diff --git a/app/helpers/officers_helper.rb b/app/helpers/officers_helper.rb new file mode 100644 index 000000000..f29bcf728 --- /dev/null +++ b/app/helpers/officers_helper.rb @@ -0,0 +1,7 @@ +module OfficersHelper + + def officer_label(officer) + truncate([officer.name, officer.email].compact.join(' - '), length: 100) + end + +end \ No newline at end of file diff --git a/app/models/poll/booth.rb b/app/models/poll/booth.rb index eb7d81b8c..74c4c3edb 100644 --- a/app/models/poll/booth.rb +++ b/app/models/poll/booth.rb @@ -2,6 +2,8 @@ class Poll class Booth < ActiveRecord::Base belongs_to :poll has_many :voters + has_many :officing_booths, dependent: :destroy + has_many :officers, through: :officing_booths validates :name, presence: true end diff --git a/app/models/poll/officing_booth.rb b/app/models/poll/officing_booth.rb new file mode 100644 index 000000000..f0a64721a --- /dev/null +++ b/app/models/poll/officing_booth.rb @@ -0,0 +1,6 @@ +class Poll + class OfficingBooth < ActiveRecord::Base + belongs_to :officer + belongs_to :booth + end +end diff --git a/app/views/admin/poll/booths/show.html.erb b/app/views/admin/poll/booths/show.html.erb index 55f7d5504..cce704d2c 100644 --- a/app/views/admin/poll/booths/show.html.erb +++ b/app/views/admin/poll/booths/show.html.erb @@ -15,34 +15,32 @@

    <%= t("admin.booths.show.officers_list") %>

    - -
    - <%= t("admin.booths.show.no_officers") %> -
    - - -<%= link_to t("admin.booths.show.assign_officer"), "#", class: "button success" %> +<% if @booth.officers.empty? %> +
    + <%= t("admin.booths.show.no_officers") %> +
    +<% end %>
    - - <%# f.label :valuator_ids, t("admin.spending_proposals.edit.assigned_valuators") %> + <%= form_for @booth, url: admin_poll_booth_path(@poll, @booth) do |f| %> - <%# f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> - <%# b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %> - <%# end %> + <%= f.label :officer_ids, t("admin.spending_proposals.edit.assigned_valuators") %> + <%= f.collection_check_boxes :officer_ids, @officers, :id, :email do |b| %> + <% b.label { b.check_box + truncate(officer_label(b.object), length: 60) } %> + <% end %> + + <%= f.submit t("admin.booths.show.assign_officer"), class: "button success" %> + <% end %>
    - - <%# @officers.each do |officer| %> - +
    + <% @booth.officers.each do |officer| %> + - <%# end %> + <% end %>
    - <%# officer.name %> - Admin + <%= officer.name %> - admin@consul.dev - <%# officer.email %> + <%= officer.email %> <%= link_to t('admin.poll_officers.officer.delete'), "#", class: "button hollow alert" %> @@ -53,5 +51,5 @@ %>
    \ No newline at end of file diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index ef294262d..c4a94a86e 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -208,7 +208,7 @@ en: location: "Location" assign_officer: "Assign officer" officers_list: "List of officers" - no_officers: "There is no officers in this booth." + no_officers: "There are no officers assigned to this booth" officials: edit: destroy: Remove 'Official' status diff --git a/db/migrate/20160928113143_create_officing_booths.rb b/db/migrate/20160928113143_create_officing_booths.rb new file mode 100644 index 000000000..00483fe00 --- /dev/null +++ b/db/migrate/20160928113143_create_officing_booths.rb @@ -0,0 +1,9 @@ +class CreateOfficingBooths < ActiveRecord::Migration + def change + create_table :poll_officing_booths do |t| + t.belongs_to :officer + t.belongs_to :booth + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 493dfbe3a..98be0a56f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160926090107) do +ActiveRecord::Schema.define(version: 20160928113143) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -280,6 +280,13 @@ ActiveRecord::Schema.define(version: 20160926090107) do t.integer "user_id" end + create_table "poll_officing_booths", force: :cascade do |t| + t.integer "officer_id" + t.integer "booth_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "poll_voters", force: :cascade do |t| t.integer "booth_id" t.string "document_number" diff --git a/spec/factories.rb b/spec/factories.rb index f7e09b7e8..92fefba11 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -267,6 +267,11 @@ FactoryGirl.define do user end + factory :officing_booth, class: 'Poll::OfficingBooth' do + association :officer, factory: :poll_officer + association :booth, factory: :poll_booth + end + factory :poll_booth, class: 'Poll::Booth' do sequence(:name) { |n| "Booth #{n}" } sequence(:location) { |n| "Street #{n}" } diff --git a/spec/features/admin/poll/officers_spec.rb b/spec/features/admin/poll/officers_spec.rb index ed9ec545d..981b17f13 100644 --- a/spec/features/admin/poll/officers_spec.rb +++ b/spec/features/admin/poll/officers_spec.rb @@ -1,12 +1,13 @@ require 'rails_helper' feature 'Admin poll officers' do + background do @admin = create(:administrator) @user = create(:user, username: 'Pedro Jose Garcia') @officer = create(:poll_officer) login_as(@admin.user) - visit admin_poll_officers_path + visit admin_officers_path end scenario 'Index' do @@ -15,7 +16,7 @@ feature 'Admin poll officers' do expect(page).to_not have_content @user.name end - scenario 'Create poll officer', :js do + scenario 'Create', :js do fill_in 'email', with: @user.email click_button 'Search' @@ -26,11 +27,133 @@ feature 'Admin poll officers' do end end - scenario 'Delete poll officer' do + scenario 'Delete' do click_link 'Delete' within("#officers") do expect(page).to_not have_content @officer.name end end + + context "Booth" do + + scenario 'No officers assigned to booth' do + poll = create(:poll) + booth = create(:poll_booth, poll: poll) + + visit admin_poll_booth_path(poll, booth) + + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 0 + end + + expect(page).to have_content "There are no officers assigned to this booth" + end + + scenario "Assigned to booth" do + john = create(:poll_officer) + isabel = create(:poll_officer) + eve = create(:poll_officer) + + poll = create(:poll) + booth = create(:poll_booth, poll: poll) + + officing_booth1 = create(:officing_booth, officer: john, booth: booth) + officing_booth2 = create(:officing_booth, officer: isabel, booth: booth) + + visit admin_poll_booth_path(poll, booth) + + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 2 + expect(page).to have_content john.name + expect(page).to have_content isabel.name + + expect(page).to_not have_content eve.name + end + + expect(page).to_not have_content "There are no officers assigned to this booth" + end + + scenario 'Assign to booth' do + john = create(:poll_officer) + isabel = create(:poll_officer) + + poll = create(:poll) + booth = create(:poll_booth, poll: poll) + + visit admin_poll_booth_path(poll, booth) + + check "#{john.name} - #{john.email}" + click_button "Assign officer" + + expect(page).to have_content "Booth updated successfully." + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 1 + expect(page).to have_content john.name + end + end + + scenario "Unassign from booth" do + john = create(:poll_officer) + isabel = create(:poll_officer) + + poll = create(:poll) + booth = create(:poll_booth, poll: poll) + + officing_booth = create(:officing_booth, officer: john, booth: booth) + officing_booth = create(:officing_booth, officer: isabel, booth: booth) + + visit admin_poll_booth_path(poll, booth) + + uncheck "#{john.name} - #{john.email}" + click_button "Assign officer" + + expect(page).to have_content "Booth updated successfully." + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 1 + expect(page).to have_content isabel.name + + expect(page).to_not have_content john.name + end + end + + scenario "Assigned multiple officers to different booths" do + john = create(:poll_officer) + isabel = create(:poll_officer) + eve = create(:poll_officer) + peter = create(:poll_officer) + + poll1 = create(:poll) + poll2 = create(:poll) + + booth1 = create(:poll_booth, poll: poll1) + booth2 = create(:poll_booth, poll: poll1) + booth3 = create(:poll_booth, poll: poll2) + + officing_booth = create(:officing_booth, officer: john, booth: booth1) + officing_booth = create(:officing_booth, officer: isabel, booth: booth1) + officing_booth = create(:officing_booth, officer: eve, booth: booth2) + officing_booth = create(:officing_booth, officer: peter, booth: booth3) + + visit admin_poll_booth_path(poll1, booth1) + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 2 + expect(page).to have_content john.name + expect(page).to have_content isabel.name + end + + visit admin_poll_booth_path(poll1, booth2) + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 1 + expect(page).to have_content eve.name + end + + visit admin_poll_booth_path(poll2, booth3) + within("#assigned_officers") do + expect(page).to have_css ".officer", count: 1 + expect(page).to have_content peter.name + end + end + end + end \ No newline at end of file From 1c75dca13a09ce93c9a71b7bde132c2b7a6a6832 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Fri, 14 Oct 2016 19:00:58 +0200 Subject: [PATCH 32/66] adds styles for offering voters views --- app/views/officing/dashboard/index.html.erb | 1 - app/views/officing/voters/new.html.erb | 21 +++++++++++++++- app/views/officing/voters/show.html.erb | 26 +++++++++++++++++++- config/locales/officing.en.yml | 18 ++++++++++++-- config/locales/officing.es.yml | 27 +++++++++++++++++++-- 5 files changed, 86 insertions(+), 7 deletions(-) diff --git a/app/views/officing/dashboard/index.html.erb b/app/views/officing/dashboard/index.html.erb index cf014d719..861a39b1a 100644 --- a/app/views/officing/dashboard/index.html.erb +++ b/app/views/officing/dashboard/index.html.erb @@ -2,5 +2,4 @@

    <%= t("officing.dashboard.index.title") %>

    <%= t("officing.dashboard.index.info") %>

    - diff --git a/app/views/officing/voters/new.html.erb b/app/views/officing/voters/new.html.erb index 0fb4c6bc3..37edfd788 100644 --- a/app/views/officing/voters/new.html.erb +++ b/app/views/officing/voters/new.html.erb @@ -1 +1,20 @@ -voters new +

    <%= t("officing.voters.new.title") %>

    + +
    +
    +
    + + + + + + "> + + " class="button"> +
    +
    +
    diff --git a/app/views/officing/voters/show.html.erb b/app/views/officing/voters/show.html.erb index fd8c83123..3de9d9651 100644 --- a/app/views/officing/voters/show.html.erb +++ b/app/views/officing/voters/show.html.erb @@ -1 +1,25 @@ -voters show \ No newline at end of file +

    <%= t("officing.voters.show.title") %>

    + + + +
    + <%= t("officing.voters.show.error_verifying_census") %> +
    + + + +
    + <%= t("officing.voters.show.error_already_voted") %> +
    + + + +
    + <%= t("officing.voters.show.success") %> +
    + +
    +
    + " class="button success expanded"> +
    +
    diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index 532d18498..c8989dfc6 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -6,5 +6,19 @@ en: title: Poll officing info: Here you can validate user documents and store voting results menu: - voters: Validate citizen document - results: Store voting results \ No newline at end of file + voters: Validate document + results: Store results + voters: + new: + title: Validate document + document_number: Document number + document_type: + passport: Passport + residence_card: Residence card + spanish_id: DNI + document_type_label: Document type + submit: Validate document + show: + title: Validate document + error_verifying_census: "The Census was unable to verify your information." + error_already_voted: "La persona asociada al documento ya ha participado en la votación." \ No newline at end of file diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index baa60b106..8ab0dc384 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -6,5 +6,28 @@ es: title: Presidir mesa de votaciones info: Aquí puedes validar documentos de ciudadanos y guardar los resultados de las urnas menu: - voters: Validar documento de identidad - results: Guardar resultados de la votación \ No newline at end of file + voters: Validar documento + results: Guardar resultados + voters: + new: + title: Validar documento + document_number: Número de documento + document_type: + passport: Pasaporte + residence_card: Tarjeta de residencia + spanish_id: DNI + document_type_label: Tipo de documento + submit: Validar documento + show: + title: Validar documento + error_verifying_census: "El Padrón no pudo verificar tu información." + error_already_voted: "La persona asociada al documento ya ha participado en la votación." + success: "La persona asociada al documento puede participar en la votación." + submit: Validar voto + results: + index: + title: "Resultados de la votación" + new: + title: "Añadir resultados" + show: + title: "Resultados" \ No newline at end of file From 5a78e51de25ed4f793d98b35e3c3e0276c328e91 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 17 Oct 2016 16:42:50 +0200 Subject: [PATCH 33/66] adds styles to officing voters views --- app/assets/stylesheets/admin.scss | 4 ++ app/views/officing/_menu.html.erb | 2 +- app/views/officing/results/index.html.erb | 55 ++++++++++++++++++++++- app/views/officing/results/new.html.erb | 39 +++++++++++++++- app/views/officing/results/show.html.erb | 51 ++++++++++++++++++++- app/views/officing/voters/new.html.erb | 2 +- app/views/officing/voters/show.html.erb | 7 ++- config/locales/officing.en.yml | 24 +++++++++- config/locales/officing.es.yml | 19 ++++++-- 9 files changed, 191 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index cd8241fca..bbb9fee4f 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -42,6 +42,10 @@ body.admin { th { text-align: left; + + &.text-center { + text-align: center; + } } tr { diff --git a/app/views/officing/_menu.html.erb b/app/views/officing/_menu.html.erb index 81734d99f..f051b5940 100644 --- a/app/views/officing/_menu.html.erb +++ b/app/views/officing/_menu.html.erb @@ -14,5 +14,5 @@ <%= t("officing.menu.results") %> <% end %>
  • - + diff --git a/app/views/officing/results/index.html.erb b/app/views/officing/results/index.html.erb index 8e9faa1ab..8e50de625 100644 --- a/app/views/officing/results/index.html.erb +++ b/app/views/officing/results/index.html.erb @@ -1 +1,54 @@ -results index \ No newline at end of file +

    <%= t("officing.results.index.title") %>

    + +
    +
    + +
    + +
    + +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <%= t("officing.shared.booth") %><%= t("officing.shared.date") %><%= t("officing.shared.officer") %><%= t("officing.shared.votes_number") %>
    <%= link_to "Urna Moncloa (1)", officing_poll_result_path(Poll.last, 1) %>14/10/2016Officer Name (officer@email.com)124
    <%= link_to "Urna Cahamartín (6)", officing_poll_result_path(Poll.last, 1) %>17/10/2016Other Officer (otherofficer@email.com)350
    <%= t("officing.results.index.total_votes") %>474
    diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index bb40dff9e..178efbadd 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -1 +1,38 @@ -results new \ No newline at end of file +

    <%= t("officing.results.new.title") %>

    + +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    + +
    +
    + + "> +
    +
    + +
    +
    + " class="button expanded"> +
    +
    +
    diff --git a/app/views/officing/results/show.html.erb b/app/views/officing/results/show.html.erb index b3ca8e29c..4c7b88e00 100644 --- a/app/views/officing/results/show.html.erb +++ b/app/views/officing/results/show.html.erb @@ -1 +1,50 @@ -results show \ No newline at end of file +<%= render 'shared/back_link' %> + +

    <%= t("officing.results.show.title", booth: "Booth Name (1)") %>

    + +
    +
    + +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <%= t("officing.shared.date") %><%= t("officing.shared.officer") %><%= t("officing.shared.votes_number") %>
    14/10/2016Officer Name (officer@email.com)124
    17/10/2016Other Officer (otherofficer@email.com)350
    18/10/2016Officer number 3 (officer3@email.com)100
    <%= t("officing.results.index.total_votes") %>574
    diff --git a/app/views/officing/voters/new.html.erb b/app/views/officing/voters/new.html.erb index 37edfd788..2042f7acb 100644 --- a/app/views/officing/voters/new.html.erb +++ b/app/views/officing/voters/new.html.erb @@ -1,7 +1,7 @@

    <%= t("officing.voters.new.title") %>

    -
    +
    diff --git a/app/views/officing/voters/show.html.erb b/app/views/officing/voters/show.html.erb index 3de9d9651..523e0e0d4 100644 --- a/app/views/officing/voters/show.html.erb +++ b/app/views/officing/voters/show.html.erb @@ -15,7 +15,7 @@
    - <%= t("officing.voters.show.success") %> + <%= t("officing.voters.show.can_participate") %>
    @@ -23,3 +23,8 @@ " class="button success expanded">
    + + +
    + <%= t("officing.voters.show.success") %> +
    \ No newline at end of file diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index c8989dfc6..20cd8fcfc 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -20,5 +20,25 @@ en: submit: Validate document show: title: Validate document - error_verifying_census: "The Census was unable to verify your information." - error_already_voted: "La persona asociada al documento ya ha participado en la votación." \ No newline at end of file + error_verifying_census: "The Census was unable to verify the information of this document." + error_already_voted: "The person associated with the document has already participated in the vote." + can_participate: "The person associated with the document can participate in the vote." + submit: Validate vote + success: "Vote validated correctly." + results: + index: + title: "Vote results" + total_votes: "Total number of votes" + new: + title: Save results + submit: Save + show: + title: "%{booth} results" + shared: + filter_booth: All booths + filter_date: All dates + filter_officer: All officers + booth: Booth + date: Date + officer: Officer + votes_number: Number of votes diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 8ab0dc384..e187365f1 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -20,14 +20,25 @@ es: submit: Validar documento show: title: Validar documento - error_verifying_census: "El Padrón no pudo verificar tu información." + error_verifying_census: "El Padrón no pudo verificar la información de este documento." error_already_voted: "La persona asociada al documento ya ha participado en la votación." - success: "La persona asociada al documento puede participar en la votación." + can_participate: "La persona asociada al documento puede participar en la votación." submit: Validar voto + success: "Voto validado correctamente." results: index: title: "Resultados de la votación" + total_votes: "Número total de votos" new: - title: "Añadir resultados" + title: Guardar resultados + submit: Guardar show: - title: "Resultados" \ No newline at end of file + title: "Resultados de %{booth}" + shared: + filter_booth: Todas las urnas + filter_date: Todas las fechas + filter_officer: Todos los presidentes de mesa + booth: Urna + date: Fecha + officer: Presidente de mesa + votes_number: Número de votos From e4d8b8732d5ca54756c593f269d6812b778942b9 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Mon, 17 Oct 2016 16:43:11 +0200 Subject: [PATCH 34/66] add officing to i18n tasks --- config/i18n-tasks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 250ed18f9..245eebbcf 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -32,6 +32,7 @@ data: - config/locales/devise_views.%{locale}.yml - config/locales/responders.%{locale}.yml - config/locales/kaminari.%{locale}.yml + - config/locales/officing.%{locale}.yml # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom: # `i18n-tasks normalize -p` will force move the keys according to these rules From 32abb1eadd8ee8b00a641e58f7c92e7d188a7331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 19 Oct 2016 13:44:05 +0200 Subject: [PATCH 35/66] removes booths link from admin menu --- app/views/admin/_menu.html.erb | 8 ---- spec/features/admin/poll/booths_spec.rb | 57 +++---------------------- 2 files changed, 5 insertions(+), 60 deletions(-) diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 0661a3bb6..11e46814d 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -95,14 +95,6 @@ <% end %> - <% if Poll.any? %> -
  • > - <%= link_to admin_poll_booths_url(Poll.last) do %> - <%= t('admin.menu.booths') %> - <% end %> -
  • - <% end %> -
  • > <%= link_to admin_activity_path do %> <%= t('admin.menu.activity') %> diff --git a/spec/features/admin/poll/booths_spec.rb b/spec/features/admin/poll/booths_spec.rb index ad46c67fb..eff653dfe 100644 --- a/spec/features/admin/poll/booths_spec.rb +++ b/spec/features/admin/poll/booths_spec.rb @@ -13,32 +13,24 @@ feature 'Admin booths' do visit admin_root_path within('#side_menu') do - click_link "Booths" + click_link "Polls" end + click_link poll.name + expect(page).to have_content "There are no booths in this poll" end - scenario 'No link to booths when no polls' do - Poll.destroy_all - - visit admin_root_path - - within('#side_menu') do - expect(page).to_not have_link "Booths" - end - end - scenario 'Index' do 3.times { create(:poll_booth, poll: poll) } visit admin_root_path within('#side_menu') do - click_link "Booths" + click_link "Polls" end - expect(page).to have_css ".booth", count: 3 + click_link poll.name booths = Poll::Booth.all booths.each do |booth| @@ -50,45 +42,6 @@ feature 'Admin booths' do expect(page).to_not have_content "There are no booths" end - scenario "Index default to last poll" do - poll1 = create(:poll) - poll2 = create(:poll) - - booth1 = create(:poll_booth, poll: poll1) - booth2 = create(:poll_booth, poll: poll2) - - visit admin_root_path - - within('#side_menu') do - click_link "Booths" - end - - expect(page).to have_css ".booth", count: 1 - expect(page).to have_content booth2.name - expect(page).to_not have_content booth1.name - end - - scenario "Index select poll", :js do - poll1 = create(:poll) - poll2 = create(:poll) - - booth1 = create(:poll_booth, poll: poll1) - booth2 = create(:poll_booth, poll: poll2) - - visit admin_root_path - - within('#side_menu') do - click_link "Booths" - end - - select poll1.name, from: "poll_id" - - expect(page).to have_content "List of booths of poll #{poll1.name}" - expect(page).to have_css ".booth", count: 1 - expect(page).to have_content booth1.name - expect(page).to_not have_content booth2.name - end - scenario 'Show' do booth = create(:poll_booth, poll: poll) From 0d3476524753a881c023b087504f4af8d153b15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 20 Oct 2016 12:31:06 +0200 Subject: [PATCH 36/66] removes unused i18n key --- config/locales/admin.en.yml | 1 - config/locales/admin.es.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index c4a94a86e..6c42ac23e 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -106,7 +106,6 @@ en: valuators: Valuators poll_officers: Poll officers polls: Polls - booths: Booths officials: Officials organizations: Organisations settings: Configuration settings diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 48dfe2959..55991e056 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -106,7 +106,6 @@ es: valuators: Evaluadores poll_officers: Presidentes de mesa polls: Votaciones - booths: Urnas officials: Cargos públicos organizations: Organizaciones settings: Configuración global From 44691a0bd73e30a9657bfbd6b1ca38492d60c3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 20 Oct 2016 16:14:03 +0200 Subject: [PATCH 37/66] adds dates to polls --- db/migrate/20161020112156_add_dates_to_polls.rb | 6 ++++++ db/schema.rb | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20161020112156_add_dates_to_polls.rb diff --git a/db/migrate/20161020112156_add_dates_to_polls.rb b/db/migrate/20161020112156_add_dates_to_polls.rb new file mode 100644 index 000000000..d504930ae --- /dev/null +++ b/db/migrate/20161020112156_add_dates_to_polls.rb @@ -0,0 +1,6 @@ +class AddDatesToPolls < ActiveRecord::Migration + def change + add_column :polls, :starts_at, :datetime + add_column :polls, :ends_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 5d81903a1..d1862bf11 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160928113143) do +ActiveRecord::Schema.define(version: 20161020112156) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -294,7 +294,9 @@ ActiveRecord::Schema.define(version: 20160928113143) do end create_table "polls", force: :cascade do |t| - t.string "name" + t.string "name" + t.datetime "starts_at" + t.datetime "ends_at" end create_table "proposal_notifications", force: :cascade do |t| From 01d337f7e96082f135e807c36dd0b49f92495dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 20 Oct 2016 16:25:02 +0200 Subject: [PATCH 38/66] changes menu name --- config/locales/admin.es.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 55991e056..024f6abe2 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -105,7 +105,7 @@ es: moderators: Moderadores valuators: Evaluadores poll_officers: Presidentes de mesa - polls: Votaciones + polls: Votaciones físicas officials: Cargos públicos organizations: Organizaciones settings: Configuración global From d279baa29a0e9d6e0bfda523b3d6b1b1fe9f7973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 20 Oct 2016 16:25:36 +0200 Subject: [PATCH 39/66] fights a flaky spec --- spec/features/account_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/features/account_spec.rb b/spec/features/account_spec.rb index d1c547185..5561e89d4 100644 --- a/spec/features/account_spec.rb +++ b/spec/features/account_spec.rb @@ -112,7 +112,11 @@ feature 'Account' do end scenario 'Errors editing credentials' do - visit account_path + visit root_path + + click_link "My account" + + expect(current_path).to eq(account_path) click_link 'Change my credentials' click_button 'Update' From 250680439371699787d033076b960b71297e35dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 27 Oct 2016 15:52:07 +0200 Subject: [PATCH 40/66] adds fields and i18n keys to admin poll form --- app/views/admin/poll/polls/_form.html.erb | 16 ++++++++++++++-- config/i18n-tasks.yml | 1 + config/locales/admin.en.yml | 12 ++++-------- config/locales/admin.es.yml | 14 +++++--------- config/locales/responders.es.yml | 4 ++-- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/app/views/admin/poll/polls/_form.html.erb b/app/views/admin/poll/polls/_form.html.erb index 77961912c..9926c679a 100644 --- a/app/views/admin/poll/polls/_form.html.erb +++ b/app/views/admin/poll/polls/_form.html.erb @@ -2,8 +2,20 @@
    <%= f.text_field :name, - placeholder: t('admin.polls.new.name'), - label: t("admin.polls.new.name") %> + placeholder: t('admin.polls.form.name'), + label: t("admin.polls.form.name") %> +
    +
    + +
    +
    + + +
    + +
    + +
    diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 5c5898783..2cf89fe64 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -120,6 +120,7 @@ ignore_unused: - 'admin.activity.show.filter*' - 'admin.comments.index.hidden_*' - 'admin.settings.index.features.*' + - 'admin.polls.*.submit_button' - 'moderation.comments.index.filter*' - 'moderation.comments.index.order*' - 'moderation.debates.index.filter*' diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 6c42ac23e..1d80aa4cd 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -160,18 +160,14 @@ en: status: "Status" new: title: "New poll" - name: "Name" - reference: "Reference number" - open_date: "Open date" - close_date: "Close date" submit_button: "Create poll" edit: title: "Edit poll" - name: "Name" - reference: "Reference number" - open_date: "Open date" - close_date: "Close date" submit_button: "Update poll" + form: + name: "Name" + starts_at: "Open date" + ends_at: "Close date" show: no_booths: "There are no booths in this poll." add_booth: "Add booth" diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 024f6abe2..cce743dcc 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -105,7 +105,7 @@ es: moderators: Moderadores valuators: Evaluadores poll_officers: Presidentes de mesa - polls: Votaciones físicas + polls: Votaciones officials: Cargos públicos organizations: Organizaciones settings: Configuración global @@ -160,18 +160,14 @@ es: status: "Estado" new: title: "Nueva votación" - name: "Nombre" - reference: "Número de referencia" - open_date: "Fecha de apertura" - close_date: "Fecha de cierre" submit_button: "Crear votación" edit: title: "Editar votación" - name: "Nombre" - reference: "Número de referencia" - open_date: "Fecha de apertura" - close_date: "Fecha de cierre" submit_button: "Actualizar votación" + form: + name: "Nombre" + starts_at: "Fecha de apertura" + ends_at: "Fecha de cierre" show: no_booths: "No hay urnas en esta votación." add_booth: "Añadir urna" diff --git a/config/locales/responders.es.yml b/config/locales/responders.es.yml index 105b00903..54c4c7035 100644 --- a/config/locales/responders.es.yml +++ b/config/locales/responders.es.yml @@ -6,7 +6,7 @@ es: notice: "%{resource_name} creado correctamente." debate: "Debate creado correctamente." direct_message: "Tu mensaje ha sido enviado correctamente." - poll: "Votación presencial creada correctamente." + poll: "Votación creada correctamente." poll_booth: "Urna creada correctamente." proposal: "Propuesta creada correctamente." proposal_notification: "Tu message ha sido enviado correctamente." @@ -17,7 +17,7 @@ es: notice: "%{resource_name} actualizado correctamente." debate: "Debate actualizado correctamente." proposal: "Propuesta actualizada correctamente." - poll: "Votación presencial actualizada correctamente." + poll: "Votación actualizada correctamente." poll_booth: "Urna actualizada correctamente." spending_proposal: "Propuesta de inversión actualizada correctamente." destroy: From 85aba10798314075c4559f5db59a0c54412a7d0a Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 28 Oct 2016 18:02:28 +0200 Subject: [PATCH 41/66] Initial work in Poll::Question --- app/models/poll/question.rb | 47 +++++++++++++++++++ .../20161028104156_create_poll_questions.rb | 21 +++++++++ ...28143204_create_geozones_poll_questions.rb | 10 ++++ db/schema.rb | 35 +++++++++++++- spec/factories.rb | 9 ++++ spec/models/poll/question_spec.rb | 27 +++++++++++ 6 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 app/models/poll/question.rb create mode 100644 db/migrate/20161028104156_create_poll_questions.rb create mode 100644 db/migrate/20161028143204_create_geozones_poll_questions.rb create mode 100644 spec/models/poll/question_spec.rb diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb new file mode 100644 index 000000000..b8815cf2d --- /dev/null +++ b/app/models/poll/question.rb @@ -0,0 +1,47 @@ +class Poll::Question < ActiveRecord::Base + include Measurable + + acts_as_paranoid column: :hidden_at + include ActsAsParanoidAliases + + belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + + has_many :comments, as: :commentable + has_many :answers + has_and_belongs_to_many :geozones + belongs_to :proposal + + validates :title, presence: true + validates :question, presence: true + validates :summary, presence: true + validates :author, presence: true + + validates :title, length: { in: 4..Poll::Question.title_max_length } + validates :description, length: { maximum: Poll::Question.description_max_length } + validates :question, length: { in: 10..Poll::Question.question_max_length } + + scope :sort_for_list, -> { order('proposal_id IS NULL', :created_at)} + scope :for_render, -> { includes(:author, :proposal) } + + def description + super.try :html_safe + end + + def valid_answers + (super.try(:split, ',').compact || []).map(&:strip) + end + + def copy_attributes_from_proposal(proposal) + if proposal.present? + self.author = proposal.author + self.author_visible_name = proposal.author.name + self.proposal_id = proposal.id + self.title = proposal.title + self.description = proposal.description + self.summary = proposal.summary + self.question = proposal.question + self.geozones = Geozone.all + end + end + +end diff --git a/db/migrate/20161028104156_create_poll_questions.rb b/db/migrate/20161028104156_create_poll_questions.rb new file mode 100644 index 000000000..13c8ac1e8 --- /dev/null +++ b/db/migrate/20161028104156_create_poll_questions.rb @@ -0,0 +1,21 @@ +class CreatePollQuestions < ActiveRecord::Migration + def change + create_table :poll_questions do |t| + t.references :proposal, index: true, foreign_key: true + t.references :poll, index: true, foreign_key: true + t.references :author, index: true # foreign key added later due to rails 4 + t.string :author_visible_name + t.string :title + t.string :question + t.string :summary + t.string :valid_answers + t.text :description + t.integer :comments_count + t.datetime :hidden_at + + t.timestamps + end + + add_foreign_key :poll_questions, :users, column: :author_id + end +end diff --git a/db/migrate/20161028143204_create_geozones_poll_questions.rb b/db/migrate/20161028143204_create_geozones_poll_questions.rb new file mode 100644 index 000000000..68077c510 --- /dev/null +++ b/db/migrate/20161028143204_create_geozones_poll_questions.rb @@ -0,0 +1,10 @@ +class CreateGeozonesPollQuestions < ActiveRecord::Migration + def change + create_table :geozones_poll_questions do |t| + t.references :geozone, index: true, foreign_key: true + t.integer :question_id, index: true + end + + add_foreign_key :geozones_poll_questions, :poll_questions, column: :question_id + end +end diff --git a/db/schema.rb b/db/schema.rb index d1862bf11..a8e6f83b3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161020112156) do +ActiveRecord::Schema.define(version: 20161028143204) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -211,6 +211,14 @@ ActiveRecord::Schema.define(version: 20161020112156) do t.string "census_code" end + create_table "geozones_poll_questions", force: :cascade do |t| + t.integer "geozone_id" + t.integer "question_id" + end + + add_index "geozones_poll_questions", ["geozone_id"], name: "index_geozones_poll_questions_on_geozone_id", using: :btree + add_index "geozones_poll_questions", ["question_id"], name: "index_geozones_poll_questions_on_question_id", using: :btree + create_table "identities", force: :cascade do |t| t.integer "user_id" t.string "provider" @@ -287,6 +295,26 @@ ActiveRecord::Schema.define(version: 20161020112156) do t.datetime "updated_at", null: false end + create_table "poll_questions", force: :cascade do |t| + t.integer "proposal_id" + t.integer "poll_id" + t.integer "author_id" + t.string "author_visible_name" + t.string "title" + t.string "question" + t.string "summary" + t.string "valid_answers" + t.text "description" + t.integer "comments_count" + t.datetime "hidden_at" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "poll_questions", ["author_id"], name: "index_poll_questions_on_author_id", using: :btree + add_index "poll_questions", ["poll_id"], name: "index_poll_questions_on_poll_id", using: :btree + add_index "poll_questions", ["proposal_id"], name: "index_poll_questions_on_proposal_id", using: :btree + create_table "poll_voters", force: :cascade do |t| t.integer "booth_id" t.string "document_number" @@ -583,12 +611,17 @@ ActiveRecord::Schema.define(version: 20161020112156) do add_foreign_key "annotations", "users" add_foreign_key "failed_census_calls", "users" add_foreign_key "flags", "users" + add_foreign_key "geozones_poll_questions", "geozones" + add_foreign_key "geozones_poll_questions", "poll_questions", column: "question_id" add_foreign_key "identities", "users" add_foreign_key "locks", "users" add_foreign_key "managers", "users" add_foreign_key "moderators", "users" add_foreign_key "notifications", "users" add_foreign_key "organizations", "users" + add_foreign_key "poll_questions", "polls" + add_foreign_key "poll_questions", "proposals" + add_foreign_key "poll_questions", "users", column: "author_id" add_foreign_key "users", "geozones" add_foreign_key "valuators", "users" end diff --git a/spec/factories.rb b/spec/factories.rb index 21abd6554..abeff338c 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -296,6 +296,15 @@ FactoryGirl.define do end end + factory :poll_question, class: 'Poll::Question' do + association :author, factory: :user + sequence(:title) { |n| "Question title #{n}" } + sequence(:summary) { |n| "Question summary #{n}" } + sequence(:description) { |n| "Question description #{n}" } + sequence(:question) { |n| "Question question #{n}" } + valid_answers { Faker::Lorem.words(3).join(', ') } + end + factory :organization do user responsible_name "Johnny Utah" diff --git a/spec/models/poll/question_spec.rb b/spec/models/poll/question_spec.rb new file mode 100644 index 000000000..92e019027 --- /dev/null +++ b/spec/models/poll/question_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe Poll::Question, type: :model do + + describe "#valid_answers" do + it "gets a comma-separated string, but returns an array" do + q = create(:poll_question, valid_answers: "Yes, No") + expect(q.valid_answers).to eq(["Yes", "No"]) + end + end + + describe "#copy_attributes_from_proposal" do + it "copies the attributes from the proposal" do + create_list(:geozone, 3) + p = create(:proposal) + q = create(:poll_question) + q.copy_attributes_from_proposal(p) + expect(q.author).to eq(p.author) + expect(q.author_visible_name).to eq(p.author.name) + expect(q.proposal_id).to eq(p.id) + expect(q.title).to eq(p.title) + expect(q.question).to eq(p.question) + expect(q.geozones).to eq(Geozone.all) + end + end + +end From 3eca3faacdbd6be272a2a72adb3a9ef0692b0afd Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 31 Oct 2016 14:13:56 +0100 Subject: [PATCH 42/66] First version of Polls Controller --- app/controllers/polls_controller.rb | 13 +++++++++++++ app/models/abilities/everyone.rb | 1 + app/views/polls/index.html.erb | 3 +++ app/views/polls/show.html.erb | 1 + config/routes.rb | 4 ++++ spec/features/polls_spec.rb | 22 ++++++++++++++++++++++ 6 files changed, 44 insertions(+) create mode 100644 app/controllers/polls_controller.rb create mode 100644 app/views/polls/index.html.erb create mode 100644 app/views/polls/show.html.erb create mode 100644 spec/features/polls_spec.rb diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb new file mode 100644 index 000000000..0c802e17f --- /dev/null +++ b/app/controllers/polls_controller.rb @@ -0,0 +1,13 @@ +class PollsController < ApplicationController + + load_and_authorize_resource + + def index + + end + + def show + + end + +end diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb index 39a7f69f5..8424500a3 100644 --- a/app/models/abilities/everyone.rb +++ b/app/models/abilities/everyone.rb @@ -6,6 +6,7 @@ module Abilities can [:read, :map], Debate can [:read, :map, :summary], Proposal can :read, Comment + can :read, Poll can :read, SpendingProposal can :read, Legislation can :read, User diff --git a/app/views/polls/index.html.erb b/app/views/polls/index.html.erb new file mode 100644 index 000000000..3a1d7f3b5 --- /dev/null +++ b/app/views/polls/index.html.erb @@ -0,0 +1,3 @@ +<% @polls.each do |poll| %> + <%= link_to poll.name, poll %> +<% end %> diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb new file mode 100644 index 000000000..01749b19a --- /dev/null +++ b/app/views/polls/show.html.erb @@ -0,0 +1 @@ +<%= @poll.name %> diff --git a/config/routes.rb b/config/routes.rb index 16625aa7c..793a97f42 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,6 +85,10 @@ Rails.application.routes.draw do get :search, on: :collection end + resources :polls, only: [:show, :index] do + resources :questions, only: [:show, :index] + end + resources :users, only: [:show] do resources :direct_messages, only: [:new, :create, :show] end diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb new file mode 100644 index 000000000..d3c101ed8 --- /dev/null +++ b/spec/features/polls_spec.rb @@ -0,0 +1,22 @@ +# coding: utf-8 +require 'rails_helper' + +feature 'Polls' do + + scenario 'Polls can be listed' do + polls = create_list(:poll, 3) + + visit polls_path + + polls.each do |poll| + expect(page).to have_link(poll.name) + end + end + + scenario 'Polls can be seen' do + poll = create(:poll) + visit poll_path(poll) + expect(page).to have_content(poll.name) + end +end + From 1aab7805920b66fcd2ebecb30ac6a4903992c49e Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 31 Oct 2016 14:27:25 +0100 Subject: [PATCH 43/66] Starts adding questions to polls --- app/models/poll.rb | 3 ++- app/models/poll/question.rb | 1 + app/views/polls/show.html.erb | 4 ++++ spec/features/polls_spec.rb | 6 ++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/models/poll.rb b/app/models/poll.rb index 4543a2544..11ac6ccb8 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -1,6 +1,7 @@ class Poll < ActiveRecord::Base has_many :booths has_many :voters, through: :booths, class_name: "Poll::Voter" + has_many :questions validates :name, presence: true -end \ No newline at end of file +end diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index b8815cf2d..75f78fb15 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -4,6 +4,7 @@ class Poll::Question < ActiveRecord::Base acts_as_paranoid column: :hidden_at include ActsAsParanoidAliases + belongs_to :poll belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' has_many :comments, as: :commentable diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index 01749b19a..e9eeb7ca2 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -1 +1,5 @@ <%= @poll.name %> + +<%= @poll.questions.sort_for_list.each do |question| %> + <%= question.title %> +<% end %> diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index d3c101ed8..a873c22f4 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -15,8 +15,14 @@ feature 'Polls' do scenario 'Polls can be seen' do poll = create(:poll) + questions = create_list(:poll_question, 5, poll: poll) + visit poll_path(poll) expect(page).to have_content(poll.name) + + questions.each do |question| + expect(page).to have_content(question.title) + end end end From 575aa62960b73a2f4a49225805a72941d8574e8c Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 31 Oct 2016 16:31:48 +0100 Subject: [PATCH 44/66] Starts introducing valid answers to poll questions --- app/controllers/polls_controller.rb | 2 +- app/models/poll/question.rb | 3 +++ app/views/polls/show.html.erb | 9 +++++++-- spec/features/polls_spec.rb | 7 ++++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 0c802e17f..f6f155106 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -7,7 +7,7 @@ class PollsController < ApplicationController end def show - + @questions = @poll.questions.sort_for_list.for_render end end diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index 75f78fb15..59ff11a70 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -23,6 +23,7 @@ class Poll::Question < ActiveRecord::Base scope :sort_for_list, -> { order('proposal_id IS NULL', :created_at)} scope :for_render, -> { includes(:author, :proposal) } + scope :by_geozone, -> (geozone_id) { joins(:geozones).where(geozones: {id: geozone_id}) } def description super.try :html_safe @@ -45,4 +46,6 @@ class Poll::Question < ActiveRecord::Base end end + + end diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index e9eeb7ca2..71870cedf 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -1,5 +1,10 @@ <%= @poll.name %> -<%= @poll.questions.sort_for_list.each do |question| %> - <%= question.title %> +<% @questions.each do |question| %> +
    + <%= question.title %> + <%= question.valid_answers.each do |valid_answer| %> + <%= link_to valid_answer %> + <% end %> +
    <% end %> diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index a873c22f4..f206407d2 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -21,7 +21,12 @@ feature 'Polls' do expect(page).to have_content(poll.name) questions.each do |question| - expect(page).to have_content(question.title) + within("#poll_question_#{question.id}") do + expect(page).to have_content(question.title) + question.valid_answers.each do |answer| + expect(page).to have_link(answer) + end + end end end end From 0305d2bd65229e6a1213a1361de5e22d3cbcdf70 Mon Sep 17 00:00:00 2001 From: kikito Date: Wed, 2 Nov 2016 17:49:34 +0100 Subject: [PATCH 45/66] Adds time scopes and methods to poll --- app/models/poll.rb | 16 ++++++++++++++++ spec/factories.rb | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/app/models/poll.rb b/app/models/poll.rb index 11ac6ccb8..cc731f0b5 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -4,4 +4,20 @@ class Poll < ActiveRecord::Base has_many :questions validates :name, presence: true + + scope :current, -> { where('starts_at <= ? and ? <= ends_at', Time.now, Time.now) } + scope :incoming, -> { where('? < starts_at', Time.now) } + scope :expired, -> { where('ends_at < ?', Time.now) } + + def current?(timestamp = DateTime.now) + starts_at <= timestamp && timestamp <= ends_at + end + + def incoming?(timestamp = DateTime.now) + timestamp < starts_at + end + + def expired?(timestamp = DateTime.now) + ends_at < timestamp + end end diff --git a/spec/factories.rb b/spec/factories.rb index abeff338c..7f9b0b63e 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -265,6 +265,19 @@ FactoryGirl.define do factory :poll do sequence(:name) { |n| "Poll #{n}" } + + starts_at { 1.month.ago } + ends_at { 1.month.from_now } + + trait :incoming do + starts_at { 2.days.from_now } + ends_at { 1.month.from_now } + end + + trait :expired do + starts_at { 1.month.ago } + ends_at { 15.days.ago } + end end factory :poll_officer, class: 'Poll::Officer' do From 3d22c556e8c71c9610cf8b1b350fd918ae56834f Mon Sep 17 00:00:00 2001 From: kikito Date: Wed, 2 Nov 2016 17:50:08 +0100 Subject: [PATCH 46/66] Adds scenarios (some missing) for poll voting --- app/views/polls/_warnings.html.erb | 28 +++++ app/views/polls/show.html.erb | 15 ++- config/locales/en.yml | 10 ++ spec/features/polls_spec.rb | 182 +++++++++++++++++++++++++---- 4 files changed, 214 insertions(+), 21 deletions(-) create mode 100644 app/views/polls/_warnings.html.erb diff --git a/app/views/polls/_warnings.html.erb b/app/views/polls/_warnings.html.erb new file mode 100644 index 000000000..b6b44fbc0 --- /dev/null +++ b/app/views/polls/_warnings.html.erb @@ -0,0 +1,28 @@ +<% if current_user.nil? %> +
    +
    + <%= t("polls.show.cant_answer_not_logged_in", + signin: link_to(t("polls.show.signin"), new_user_session_path, class: "probe-message"), + signup: link_to(t("polls.show.signup"), new_user_registration_path, class: "probe-message")).html_safe %> +
    +
    +<% elsif current_user.unverified? %> +
    +
    + <%= t('polls.show.cant_answer_verify_html', + verify_link: link_to(t('polls.show.verify_link'), verification_path)) %> +
    +
    +<% elsif @poll.incoming? %> +
    +
    + <%= t('polls.show.cant_answer_incoming') %> +
    +
    +<% elsif @poll.expired? %> +
    +
    + <%= t('polls.show.cant_answer_expired') %> +
    +
    +<% end %> diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index 71870cedf..90965e739 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -1,10 +1,23 @@ <%= @poll.name %> +<%= render 'warnings' %> + <% @questions.each do |question| %>
    <%= question.title %> + <%= question.valid_answers.each do |valid_answer| %> - <%= link_to valid_answer %> + <% if can? :answer, @poll %> + <%= link_to valid_answer %> + <% else %> + <%= valid_answer %> + <% end %> + <% end %> + + <% if false #wrong geozone %> +
    + <%= t('polls.show.cant_answer_wrong_geozone') %> +
    <% end %>
    <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 9230ecbf8..d139b724b 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -375,6 +375,16 @@ en: update: form: submit_button: Save changes + polls: + show: + cant_answer_not_logged_in: "You must %{signin} or %{signup} to participate." + signin: Sign in + signup: Sign up + cant_answer_verify_html: "You must %{verify_link} in order to answer." + verify_link: "verify your account" + cant_answer_incoming: "This poll has not yet started." + cant_answer_expired: "This poll has finished." + cant_answer_wrong_geozone: "This enquiry is not available on your geozone." proposal_ballots: title: "Votings" description_html: "The following citizen proposals that have reached the required supports and will be voted." diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index f206407d2..a226f8a65 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -3,31 +3,173 @@ require 'rails_helper' feature 'Polls' do - scenario 'Polls can be listed' do - polls = create_list(:poll, 3) + context '#index' do - visit polls_path + scenario 'Polls can be listed' do + polls = create_list(:poll, 3) - polls.each do |poll| - expect(page).to have_link(poll.name) - end - end + visit polls_path - scenario 'Polls can be seen' do - poll = create(:poll) - questions = create_list(:poll_question, 5, poll: poll) - - visit poll_path(poll) - expect(page).to have_content(poll.name) - - questions.each do |question| - within("#poll_question_#{question.id}") do - expect(page).to have_content(question.title) - question.valid_answers.each do |answer| - expect(page).to have_link(answer) - end + polls.each do |poll| + expect(page).to have_link(poll.name) end end + + xscenario 'Filtering enquiries' do + create(:poll_question, poll: poll, title: "Open question") + create(:poll_question, :incoming, poll: poll, title: "Incoming question") + create(:poll_question, :expired, poll: poll, title: "Expired question") + + visit enquiries_path + expect(page).to have_content('Open question') + expect(page).to_not have_content('Incoming question') + expect(page).to_not have_content('Expired question') + + visit enquiries_path(filter: 'incoming') + expect(page).to_not have_content('Open question') + expect(page).to have_content('Incoming question') + expect(page).to_not have_content('Expired question') + + visit enquiries_path(filter: 'expired') + expect(page).to_not have_content('Open question') + expect(page).to_not have_content('Incoming question') + expect(page).to have_content('Expired question') + end + + xscenario "Current filter is properly highlighted" do + visit enquiries_path + expect(page).to_not have_link('Open') + expect(page).to have_link('Incoming') + expect(page).to have_link('Expired') + + visit enquiries_path(filter: 'incoming') + expect(page).to have_link('Open') + expect(page).to_not have_link('Incoming') + expect(page).to have_link('Expired') + + visit enquiries_path(filter: 'expired') + expect(page).to have_link('Open') + expect(page).to have_link('Incoming') + expect(page).to_not have_link('Expired') + end end + + context 'Show' do + let(:geozone) { create(:geozone) } + let(:poll) { create(:poll) } + + scenario 'Lists questions from proposals as well as regular ones' do + normal_question = create(:poll_question, poll: poll) + proposal_question = create(:poll_question, poll: poll, proposal: create(:proposal)) + + visit poll_path(poll) + expect(page).to have_content(poll.name) + + expect(page).to have_content(normal_question.title) + expect(page).to have_content(proposal_question.title) + end + + scenario 'Non-logged in users' do + create(:poll_question, poll: poll, valid_answers: 'Han Solo, Chewbacca') + visit poll_path(poll) + + expect(page).to have_content('Han Solo') + expect(page).to have_content('Chewbacca') + expect(page).to have_content('You must Sign in or Sign up to participate') + + expect(page).to_not have_link('Han Solo') + expect(page).to_not have_link('Chewbacca') + end + + scenario 'Level 1 users' do + create(:poll_question, poll: poll, geozone_ids: [geozone.id], valid_answers: 'Han Solo, Chewbacca') + login_as(create(:user, geozone: geozone)) + visit poll_path(poll) + + expect(page).to have_content('Han Solo') + expect(page).to have_content('Chewbacca') + expect(page).to have_content('You must verify your account in order to answer') + + expect(page).to_not have_link('Han Solo') + expect(page).to_not have_link('Chewbacca') + end + + scenario 'Level 2 users in an incoming question' do + incoming_poll = create(:poll, :incoming) + create(:poll_question, poll: incoming_poll, geozone_ids: [geozone.id], valid_answers: 'Rey, Finn') + login_as(create(:user, :level_two, geozone: geozone)) + + visit poll_path(incoming_poll) + + expect(page).to have_content('Rey') + expect(page).to have_content('Finn') + expect(page).to_not have_link('Rey') + expect(page).to_not have_link('Finn') + + expect(page).to have_content('This poll has not yet started') + end + + scenario 'Level 2 users in an expired question' do + expired_poll = create(:poll, :expired) + create(:poll_question, poll: expired_poll, geozone_ids: [geozone.id], valid_answers: 'Luke, Leia') + login_as(create(:user, :level_two, geozone: geozone)) + + visit poll_path(expired_poll) + + expect(page).to have_content('Luke') + expect(page).to have_content('Leia') + expect(page).to_not have_link('Luke') + expect(page).to_not have_link('Leia') + + expect(page).to have_content('This poll has finished') + end + + xscenario 'Level 2 users in an question for a geozone which is not theirs' do + create(:poll_question, poll: poll, geozone_ids: [], valid_answers: 'Vader, Palpatine') + login_as(create(:user, :level_two)) + + visit poll_path(poll) + + expect(page).to have_content('Vader') + expect(page).to have_content('Palpatine') + expect(page).to_not have_link('Vader') + expect(page).to_not have_link('Palpatine') + end + + xscenario 'Level 2 users who can answer' do + create(:poll_question, poll: poll, geozone_ids: [geozone.id], valid_answers: 'Han Solo, Chewbacca') + login_as(create(:user, :level_two, geozone: geozone)) + visit poll_path(poll) + + expect(page).to have_link('Han Solo') + expect(page).to have_link('Chewbacca') + end + + xscenario 'Level 2 users who have already answered' do + question = create(:poll_question, poll: poll, geozone_ids:[geozone.id], valid_answers: 'Han Solo, Chewbacca') + user = create(:user, :level_two, geozone: geozone) + create(:question_answer, question: question, author: user, answer: 'Chewbacca') + login_as user + visit poll_path(poll) + + expect(page).to have_link('Han Solo') + expect(page).to_not have_link('Chewbacca') + expect(page).to have_content('Chewbacca') + end + + xscenario 'Level 2 users answering', :js do + create(:poll_question, poll: poll, geozone_ids: [geozone.id], valid_answers: 'Han Solo, Chewbacca') + user = create(:user, :level_two, geozone: geozone) + login_as user + visit poll_path(poll) + + click_link 'Han Solo' + + expect(page).to_not have_link('Han Solo') + expect(page).to have_link('Chewbacca') + end + + end + end From 35a5136d9ff3af1f71f83221921ad42cf7064a18 Mon Sep 17 00:00:00 2001 From: kikito Date: Thu, 3 Nov 2016 17:52:15 +0100 Subject: [PATCH 47/66] Implements filtering in polls/index --- app/controllers/polls_controller.rb | 4 ++- app/models/poll.rb | 2 ++ app/views/polls/index.html.erb | 4 +++ spec/features/polls_spec.rb | 46 ++++++++++++++--------------- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index f6f155106..7433ea95b 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -2,8 +2,10 @@ class PollsController < ApplicationController load_and_authorize_resource - def index + has_filters %w{current expired incoming} + def index + @polls = @polls.send(@current_filter).sort_for_list.page(params[:page]) end def show diff --git a/app/models/poll.rb b/app/models/poll.rb index cc731f0b5..a4435d321 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -9,6 +9,8 @@ class Poll < ActiveRecord::Base scope :incoming, -> { where('? < starts_at', Time.now) } scope :expired, -> { where('ends_at < ?', Time.now) } + scope :sort_for_list, -> { order(:starts_at) } + def current?(timestamp = DateTime.now) starts_at <= timestamp && timestamp <= ends_at end diff --git a/app/views/polls/index.html.erb b/app/views/polls/index.html.erb index 3a1d7f3b5..4b39e09af 100644 --- a/app/views/polls/index.html.erb +++ b/app/views/polls/index.html.erb @@ -1,3 +1,7 @@ +<%= render 'shared/filter_subnav', i18n_namespace: "polls.index" %> + <% @polls.each do |poll| %> <%= link_to poll.name, poll %> <% end %> + +<%= paginate @polls %> diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index a226f8a65..4ef146f72 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -15,40 +15,40 @@ feature 'Polls' do end end - xscenario 'Filtering enquiries' do - create(:poll_question, poll: poll, title: "Open question") - create(:poll_question, :incoming, poll: poll, title: "Incoming question") - create(:poll_question, :expired, poll: poll, title: "Expired question") + scenario 'Filtering polls' do + create(:poll, name: "Current poll") + create(:poll, :incoming, name: "Incoming poll") + create(:poll, :expired, name: "Expired poll") - visit enquiries_path - expect(page).to have_content('Open question') - expect(page).to_not have_content('Incoming question') - expect(page).to_not have_content('Expired question') + visit polls_path + expect(page).to have_content('Current poll') + expect(page).to_not have_content('Incoming poll') + expect(page).to_not have_content('Expired poll') - visit enquiries_path(filter: 'incoming') - expect(page).to_not have_content('Open question') - expect(page).to have_content('Incoming question') - expect(page).to_not have_content('Expired question') + visit polls_path(filter: 'incoming') + expect(page).to_not have_content('Current poll') + expect(page).to have_content('Incoming poll') + expect(page).to_not have_content('Expired poll') - visit enquiries_path(filter: 'expired') - expect(page).to_not have_content('Open question') - expect(page).to_not have_content('Incoming question') - expect(page).to have_content('Expired question') + visit polls_path(filter: 'expired') + expect(page).to_not have_content('Current poll') + expect(page).to_not have_content('Incoming poll') + expect(page).to have_content('Expired poll') end - xscenario "Current filter is properly highlighted" do - visit enquiries_path - expect(page).to_not have_link('Open') + scenario "Current filter is properly highlighted" do + visit polls_path + expect(page).to_not have_link('Current') expect(page).to have_link('Incoming') expect(page).to have_link('Expired') - visit enquiries_path(filter: 'incoming') - expect(page).to have_link('Open') + visit polls_path(filter: 'incoming') + expect(page).to have_link('Current') expect(page).to_not have_link('Incoming') expect(page).to have_link('Expired') - visit enquiries_path(filter: 'expired') - expect(page).to have_link('Open') + visit polls_path(filter: 'expired') + expect(page).to have_link('Current') expect(page).to have_link('Incoming') expect(page).to_not have_link('Expired') end From f821d7beb734d9d7da2f9025d11de581b8e5b328 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 10:37:22 +0100 Subject: [PATCH 48/66] Implements abilities for poll & poll_question --- app/models/abilities/common.rb | 2 ++ spec/models/abilities/common_spec.rb | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index f82e78b58..5635cc7d7 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -48,6 +48,8 @@ module Abilities can :create, SpendingProposal can :create, DirectMessage can :show, DirectMessage, sender_id: user.id + can(:answer, Poll, Poll.current){ |poll| poll.current? } + can :answer, Poll::Question, geozones: {id: user.geozone_id} end can [:create, :show], ProposalNotification, proposal: { author_id: user.id } diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb index ab14c01bd..6be4e0dce 100644 --- a/spec/models/abilities/common_spec.rb +++ b/spec/models/abilities/common_spec.rb @@ -3,8 +3,9 @@ require 'cancan/matchers' describe "Abilities::Common" do subject(:ability) { Ability.new(user) } + let(:geozone) { create(:geozone) } - let(:user) { create(:user) } + let(:user) { create(:user, geozone: geozone) } let(:debate) { create(:debate) } let(:comment) { create(:comment) } @@ -13,6 +14,13 @@ describe "Abilities::Common" do let(:own_comment) { create(:comment, author: user) } let(:own_proposal) { create(:proposal, author: user) } + let(:current_poll) { create(:poll) } + let(:incoming_poll) { create(:poll, :incoming) } + let(:expired_poll) { create(:poll, :expired) } + + let(:poll_question_from_own_geozone) { create(:poll_question, geozones: [geozone]) } + let(:poll_question_from_other_geozone) { create(:poll_question, geozones: [create(:geozone)]) } + it { should be_able_to(:index, Debate) } it { should be_able_to(:show, debate) } it { should be_able_to(:vote, debate) } @@ -103,6 +111,13 @@ describe "Abilities::Common" do it { should be_able_to(:create, DirectMessage) } it { should be_able_to(:show, own_direct_message) } it { should_not be_able_to(:show, create(:direct_message)) } + + it { should be_able_to(:answer, current_poll) } + it { should_not be_able_to(:answer, expired_poll) } + it { should_not be_able_to(:answer, incoming_poll) } + + it { should be_able_to(:answer, poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, poll_question_from_other_geozone ) } end describe "when level 3 verified" do @@ -121,5 +136,12 @@ describe "Abilities::Common" do it { should be_able_to(:create, DirectMessage) } it { should be_able_to(:show, own_direct_message) } it { should_not be_able_to(:show, create(:direct_message)) } + + it { should be_able_to(:answer, current_poll) } + it { should_not be_able_to(:answer, expired_poll) } + it { should_not be_able_to(:answer, incoming_poll) } + + it { should be_able_to(:answer, poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, poll_question_from_other_geozone ) } end end From 09cb25af30d6a32738d6dccbbe77f3c4ee63d5e3 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 16:27:34 +0100 Subject: [PATCH 49/66] Adds all_geozones to poll_questions --- .../20161107124207_add_all_geozones_to_poll_questions.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20161107124207_add_all_geozones_to_poll_questions.rb diff --git a/db/migrate/20161107124207_add_all_geozones_to_poll_questions.rb b/db/migrate/20161107124207_add_all_geozones_to_poll_questions.rb new file mode 100644 index 000000000..15ed41ba5 --- /dev/null +++ b/db/migrate/20161107124207_add_all_geozones_to_poll_questions.rb @@ -0,0 +1,5 @@ +class AddAllGeozonesToPollQuestions < ActiveRecord::Migration + def change + add_column :poll_questions, :all_geozones, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index a8e6f83b3..4e5e3d9e0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161028143204) do +ActiveRecord::Schema.define(version: 20161107124207) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -309,6 +309,7 @@ ActiveRecord::Schema.define(version: 20161028143204) do t.datetime "hidden_at" t.datetime "created_at" t.datetime "updated_at" + t.boolean "all_geozones", default: false end add_index "poll_questions", ["author_id"], name: "index_poll_questions_on_author_id", using: :btree From fd3f00d61ae91cee43191c006e49e5b499831718 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 16:27:48 +0100 Subject: [PATCH 50/66] Adds missing poll to poll_question factory --- spec/factories.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/factories.rb b/spec/factories.rb index 7f9b0b63e..219334b85 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -310,6 +310,7 @@ FactoryGirl.define do end factory :poll_question, class: 'Poll::Question' do + poll association :author, factory: :user sequence(:title) { |n| "Question title #{n}" } sequence(:summary) { |n| "Question summary #{n}" } From d39f19abb8e972edc2a291ca6ca043ca5a63ac2a Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 16:28:39 +0100 Subject: [PATCH 51/66] Defines Poll::Question#answerable_by?(user) and uses it in abilities --- app/models/abilities/common.rb | 4 ++- app/models/poll/question.rb | 11 +++++++ spec/models/abilities/common_spec.rb | 47 ++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 5635cc7d7..9d6ad84a8 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -49,7 +49,9 @@ module Abilities can :create, DirectMessage can :show, DirectMessage, sender_id: user.id can(:answer, Poll, Poll.current){ |poll| poll.current? } - can :answer, Poll::Question, geozones: {id: user.geozone_id} + can(:answer, Poll::Question, Poll::Question.answerable_by(user)) do |question| + question.answerable_by?(user) + end end can [:create, :show], ProposalNotification, proposal: { author_id: user.id } diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index 59ff11a70..6d56a31f2 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -46,6 +46,17 @@ class Poll::Question < ActiveRecord::Base end end + def answerable_by?(user) + user.present? && poll.current? && (self.all_geozones || self.geozone_ids.include?(user.geozone_id)) + end + def self.answerable_by(user) + return where(false) unless user.present? + where(poll_id: Poll.current.pluck(:id)) + .joins(:geozones) + .where('poll_questions.all_geozones = ? or geozones.id = ?', + true, + user.geozone_id || -1) # user.geozone_id can be nil, which would throw errors on sql + end end diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb index 6be4e0dce..59618f785 100644 --- a/spec/models/abilities/common_spec.rb +++ b/spec/models/abilities/common_spec.rb @@ -20,6 +20,13 @@ describe "Abilities::Common" do let(:poll_question_from_own_geozone) { create(:poll_question, geozones: [geozone]) } let(:poll_question_from_other_geozone) { create(:poll_question, geozones: [create(:geozone)]) } + let(:poll_question_from_all_geozones) { create(:poll_question, all_geozones: true) } + let(:expired_poll_question_from_own_geozone) { create(:poll_question, poll: expired_poll, geozones: [geozone]) } + let(:expired_poll_question_from_other_geozone) { create(:poll_question, poll: expired_poll, geozones: [create(:geozone)]) } + let(:expired_poll_question_from_all_geozones) { create(:poll_question, poll: expired_poll, all_geozones: true) } + let(:incoming_poll_question_from_own_geozone) { create(:poll_question, poll: incoming_poll, geozones: [geozone]) } + let(:incoming_poll_question_from_other_geozone) { create(:poll_question, poll: incoming_poll, geozones: [create(:geozone)]) } + let(:incoming_poll_question_from_all_geozones) { create(:poll_question, poll: incoming_poll, all_geozones: true) } it { should be_able_to(:index, Debate) } it { should be_able_to(:show, debate) } @@ -117,7 +124,27 @@ describe "Abilities::Common" do it { should_not be_able_to(:answer, incoming_poll) } it { should be_able_to(:answer, poll_question_from_own_geozone ) } + it { should be_able_to(:answer, poll_question_from_all_geozones ) } it { should_not be_able_to(:answer, poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone ) } + + context "without geozone" do + before(:each) { user.geozone = nil } + it { should_not be_able_to(:answer, poll_question_from_own_geozone ) } + it { should be_able_to(:answer, poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone ) } + end end describe "when level 3 verified" do @@ -142,6 +169,26 @@ describe "Abilities::Common" do it { should_not be_able_to(:answer, incoming_poll) } it { should be_able_to(:answer, poll_question_from_own_geozone ) } + it { should be_able_to(:answer, poll_question_from_all_geozones ) } it { should_not be_able_to(:answer, poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone ) } + + context "without geozone" do + before(:each) { user.geozone = nil } + it { should_not be_able_to(:answer, poll_question_from_own_geozone ) } + it { should be_able_to(:answer, poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, expired_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, expired_poll_question_from_other_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_own_geozone ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_all_geozones ) } + it { should_not be_able_to(:answer, incoming_poll_question_from_other_geozone ) } + end end end From 83fd70b0486ce81a0ecf57e254884c87f7648c64 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 17:34:24 +0100 Subject: [PATCH 52/66] Extracts some logic from poll_question to poll --- app/models/poll.rb | 9 +++++++++ app/models/poll/question.rb | 7 ++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/models/poll.rb b/app/models/poll.rb index a4435d321..caa374dc8 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -22,4 +22,13 @@ class Poll < ActiveRecord::Base def expired?(timestamp = DateTime.now) ends_at < timestamp end + + def answerable_by?(user) + user.present? && user.level_two_or_three_verified? && current? + end + + def self.answerable_by(user) + return none if user.nil? || user.unverified? + current + end end diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index 6d56a31f2..d6534e420 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -47,12 +47,13 @@ class Poll::Question < ActiveRecord::Base end def answerable_by?(user) - user.present? && poll.current? && (self.all_geozones || self.geozone_ids.include?(user.geozone_id)) + poll.answerable_by?(user) && (self.all_geozones || self.geozone_ids.include?(user.geozone_id)) end def self.answerable_by(user) - return where(false) unless user.present? - where(poll_id: Poll.current.pluck(:id)) + return none if user.nil? || user.unverified? + + where(poll_id: Poll.answerable_by(user).pluck(:id)) .joins(:geozones) .where('poll_questions.all_geozones = ? or geozones.id = ?', true, From 3255ca700f6d40c4509e782ce0e6cad56aa3aa64 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 17:42:52 +0100 Subject: [PATCH 53/66] User new answerable_by method in ability --- app/models/abilities/common.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 9d6ad84a8..36ce698b1 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -48,7 +48,7 @@ module Abilities can :create, SpendingProposal can :create, DirectMessage can :show, DirectMessage, sender_id: user.id - can(:answer, Poll, Poll.current){ |poll| poll.current? } + can(:answer, Poll, Poll.answerable_by(user)){ |poll| poll.answerable_by?(user) } can(:answer, Poll::Question, Poll::Question.answerable_by(user)) do |question| question.answerable_by?(user) end From 506cf0dd7090199cc0c9680296ad52b320e12ac2 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 7 Nov 2016 17:43:53 +0100 Subject: [PATCH 54/66] Refactors polls_controller using answerable_by. Implements more specs --- app/controllers/polls_controller.rb | 5 ++- app/views/polls/_warnings.html.erb | 28 ------------- app/views/polls/show.html.erb | 62 +++++++++++++++++++++-------- config/locales/en.yml | 2 +- spec/features/polls_spec.rb | 7 +++- 5 files changed, 56 insertions(+), 48 deletions(-) delete mode 100644 app/views/polls/_warnings.html.erb diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 7433ea95b..28ce9c447 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -9,7 +9,10 @@ class PollsController < ApplicationController end def show - @questions = @poll.questions.sort_for_list.for_render + questions = @poll.questions.sort_for_list.for_render + + @answerable_questions = questions.answerable_by(current_user) + @non_answerable_questions = questions.where.not(id: @answerable_questions.pluck(:id)) end end diff --git a/app/views/polls/_warnings.html.erb b/app/views/polls/_warnings.html.erb deleted file mode 100644 index b6b44fbc0..000000000 --- a/app/views/polls/_warnings.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -<% if current_user.nil? %> -
    -
    - <%= t("polls.show.cant_answer_not_logged_in", - signin: link_to(t("polls.show.signin"), new_user_session_path, class: "probe-message"), - signup: link_to(t("polls.show.signup"), new_user_registration_path, class: "probe-message")).html_safe %> -
    -
    -<% elsif current_user.unverified? %> -
    -
    - <%= t('polls.show.cant_answer_verify_html', - verify_link: link_to(t('polls.show.verify_link'), verification_path)) %> -
    -
    -<% elsif @poll.incoming? %> -
    -
    - <%= t('polls.show.cant_answer_incoming') %> -
    -
    -<% elsif @poll.expired? %> -
    -
    - <%= t('polls.show.cant_answer_expired') %> -
    -
    -<% end %> diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index 90965e739..a51f280fb 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -1,23 +1,53 @@ <%= @poll.name %> -<%= render 'warnings' %> - -<% @questions.each do |question| %> -
    - <%= question.title %> - - <%= question.valid_answers.each do |valid_answer| %> - <% if can? :answer, @poll %> - <%= link_to valid_answer %> - <% else %> - <%= valid_answer %> - <% end %> - <% end %> - - <% if false #wrong geozone %> +<% unless can?(:answer, @poll) %> +
    + <% if current_user.nil? %> +
    + <%= t("polls.show.cant_answer_not_logged_in", + signin: link_to(t("polls.show.signin"), new_user_session_path, class: "probe-message"), + signup: link_to(t("polls.show.signup"), new_user_registration_path, class: "probe-message")).html_safe %> +
    + <% elsif current_user.unverified? %>
    - <%= t('polls.show.cant_answer_wrong_geozone') %> + <%= t('polls.show.cant_answer_verify_html', + verify_link: link_to(t('polls.show.verify_link'), verification_path)) %> +
    + <% elsif @poll.incoming? %> +
    + <%= t('polls.show.cant_answer_incoming') %> +
    + <% elsif @poll.expired? %> +
    + <%= t('polls.show.cant_answer_expired') %>
    <% end %>
    <% end %> + +<% @answerable_questions.each do |question| %> +
    + <%= question.title %> + + <% question.valid_answers.each do |valid_answer| %> + <%= link_to valid_answer %> + <% end %> +
    +<% end %> + +<% if can?(:answer, @poll) && + @non_answerable_questions.present? %> +
    + <%= t('polls.show.cant_answer_wrong_geozone') %> +
    +<% end %> + +<% @non_answerable_questions.each do |question| %> +
    + <%= question.title %> + + <% question.valid_answers.each do |valid_answer| %> + <%= valid_answer %> + <% end %> +
    +<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d139b724b..b032b5805 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -384,7 +384,7 @@ en: verify_link: "verify your account" cant_answer_incoming: "This poll has not yet started." cant_answer_expired: "This poll has finished." - cant_answer_wrong_geozone: "This enquiry is not available on your geozone." + cant_answer_wrong_geozone: "The following questions are not available in your geozone." proposal_ballots: title: "Votings" description_html: "The following citizen proposals that have reached the required supports and will be voted." diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index 4ef146f72..a0da259aa 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -86,9 +86,10 @@ feature 'Polls' do login_as(create(:user, geozone: geozone)) visit poll_path(poll) + expect(page).to have_content('You must verify your account in order to answer') + expect(page).to have_content('Han Solo') expect(page).to have_content('Chewbacca') - expect(page).to have_content('You must verify your account in order to answer') expect(page).to_not have_link('Han Solo') expect(page).to_not have_link('Chewbacca') @@ -124,12 +125,14 @@ feature 'Polls' do expect(page).to have_content('This poll has finished') end - xscenario 'Level 2 users in an question for a geozone which is not theirs' do + scenario 'Level 2 users in a poll with questions for a geozone which is not theirs' do create(:poll_question, poll: poll, geozone_ids: [], valid_answers: 'Vader, Palpatine') login_as(create(:user, :level_two)) visit poll_path(poll) + expect(page).to have_content('The following questions are not available in your geozone') + expect(page).to have_content('Vader') expect(page).to have_content('Palpatine') expect(page).to_not have_link('Vader') From 6dd2b54123e1a066cfce9e0e2f2900b16c6a9cf1 Mon Sep 17 00:00:00 2001 From: kikito Date: Tue, 8 Nov 2016 15:52:13 +0100 Subject: [PATCH 55/66] Fixes bug in Poll::Question#answerable_by --- app/models/poll/question.rb | 4 ++-- spec/features/polls_spec.rb | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index d6534e420..ae90ada12 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -54,8 +54,8 @@ class Poll::Question < ActiveRecord::Base return none if user.nil? || user.unverified? where(poll_id: Poll.answerable_by(user).pluck(:id)) - .joins(:geozones) - .where('poll_questions.all_geozones = ? or geozones.id = ?', + .joins('LEFT OUTER JOIN "geozones_poll_questions" ON "geozones_poll_questions"."question_id" = "poll_questions"."id"') + .where('(poll_questions.all_geozones = ? or geozones_poll_questions.geozone_id = ?)', true, user.geozone_id || -1) # user.geozone_id can be nil, which would throw errors on sql end diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index a0da259aa..31e7e0d8b 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -148,6 +148,16 @@ feature 'Polls' do expect(page).to have_link('Chewbacca') end + scenario 'Level 2 users reading a all-geozones question' do + create(:poll_question, poll: poll, all_geozones: true, valid_answers: 'Han Solo, Chewbacca') + login_as(create(:user, :level_two, geozone: geozone)) + visit poll_path(poll) + save_and_open_page + + expect(page).to have_link('Han Solo') + expect(page).to have_link('Chewbacca') + end + xscenario 'Level 2 users who have already answered' do question = create(:poll_question, poll: poll, geozone_ids:[geozone.id], valid_answers: 'Han Solo, Chewbacca') user = create(:user, :level_two, geozone: geozone) From 4db6ae489f7226100868d9a6dcc310c23e35015f Mon Sep 17 00:00:00 2001 From: kikito Date: Tue, 8 Nov 2016 15:53:49 +0100 Subject: [PATCH 56/66] Adds new passing test to poll questions --- spec/features/polls_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index 31e7e0d8b..f44ccfd94 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -139,7 +139,7 @@ feature 'Polls' do expect(page).to_not have_link('Palpatine') end - xscenario 'Level 2 users who can answer' do + scenario 'Level 2 users reading a same-geozone question' do create(:poll_question, poll: poll, geozone_ids: [geozone.id], valid_answers: 'Han Solo, Chewbacca') login_as(create(:user, :level_two, geozone: geozone)) visit poll_path(poll) From 3ce7f671fbe129f74f1fd24dbf17da321efb95c9 Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:08:15 +0100 Subject: [PATCH 57/66] Adds poll partial result --- ...20161107174423_create_poll_partial_result.rb | 14 ++++++++++++++ db/schema.rb | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20161107174423_create_poll_partial_result.rb diff --git a/db/migrate/20161107174423_create_poll_partial_result.rb b/db/migrate/20161107174423_create_poll_partial_result.rb new file mode 100644 index 000000000..a4f91a4f9 --- /dev/null +++ b/db/migrate/20161107174423_create_poll_partial_result.rb @@ -0,0 +1,14 @@ +class CreatePollPartialResult < ActiveRecord::Migration + def change + create_table :poll_partial_results do |t| + t.integer :question_id, index: true + t.integer :author_id, index: true + t.string :answer, index: true + t.integer :amount + t.string :origin, index: true + end + + add_foreign_key(:poll_partial_results, :users, column: :author_id) + add_foreign_key(:poll_partial_results, :poll_questions, column: :question_id) + end +end diff --git a/db/schema.rb b/db/schema.rb index 4e5e3d9e0..6a94a95dc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161107124207) do +ActiveRecord::Schema.define(version: 20161107174423) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -295,6 +295,19 @@ ActiveRecord::Schema.define(version: 20161107124207) do t.datetime "updated_at", null: false end + create_table "poll_partial_results", force: :cascade do |t| + t.integer "question_id" + t.integer "author_id" + t.string "answer" + t.integer "amount" + t.string "origin" + end + + add_index "poll_partial_results", ["answer"], name: "index_poll_partial_results_on_answer", using: :btree + add_index "poll_partial_results", ["author_id"], name: "index_poll_partial_results_on_author_id", using: :btree + add_index "poll_partial_results", ["origin"], name: "index_poll_partial_results_on_origin", using: :btree + add_index "poll_partial_results", ["question_id"], name: "index_poll_partial_results_on_question_id", using: :btree + create_table "poll_questions", force: :cascade do |t| t.integer "proposal_id" t.integer "poll_id" @@ -620,6 +633,8 @@ ActiveRecord::Schema.define(version: 20161107124207) do add_foreign_key "moderators", "users" add_foreign_key "notifications", "users" add_foreign_key "organizations", "users" + add_foreign_key "poll_partial_results", "poll_questions", column: "question_id" + add_foreign_key "poll_partial_results", "users", column: "author_id" add_foreign_key "poll_questions", "polls" add_foreign_key "poll_questions", "proposals" add_foreign_key "poll_questions", "users", column: "author_id" From 048ada3e175eb25f8e7e080a4a8bb022b9f578fe Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:08:32 +0100 Subject: [PATCH 58/66] Adds poll partial result --- app/models/poll/partial_result.rb | 18 ++++++++++++++++++ spec/models/poll/partial_result_spec.rb | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 app/models/poll/partial_result.rb create mode 100644 spec/models/poll/partial_result_spec.rb diff --git a/app/models/poll/partial_result.rb b/app/models/poll/partial_result.rb new file mode 100644 index 000000000..202f147bd --- /dev/null +++ b/app/models/poll/partial_result.rb @@ -0,0 +1,18 @@ +class Poll::PartialResult < ActiveRecord::Base + + VALID_ORIGINS = %w{ web } + + belongs_to :question, -> { with_hidden } + belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + + validates :question, presence: true + validates :author, presence: true + validates :answer, presence: true + validates :answer, inclusion: {in: ->(a) { a.question.valid_answers }} + validates :origin, inclusion: {in: VALID_ORIGINS} + + scope :by_author, -> (author_id) { where(author_id: author_id) } + scope :by_question, -> (question_id) { where(question_id: question_id) } + + +end diff --git a/spec/models/poll/partial_result_spec.rb b/spec/models/poll/partial_result_spec.rb new file mode 100644 index 000000000..ef47ecd8c --- /dev/null +++ b/spec/models/poll/partial_result_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +describe Poll::PartialResult, type: :model do + + describe "validations" do + it "validates that the answers are included in the Enquiry's list" do + q = create(:poll_question, valid_answers: 'One, Two, Three') + expect(build(:poll_partial_result, question: q, answer: 'One')).to be_valid + expect(build(:poll_partial_result, question: q, answer: 'Two')).to be_valid + expect(build(:poll_partial_result, question: q, answer: 'Three')).to be_valid + + expect(build(:poll_partial_result, question: q, answer: 'Four')).to_not be_valid + end + end + +end From 63311d6cd1077173d68f226390a9e4f38ba47ba2 Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:08:46 +0100 Subject: [PATCH 59/66] reimplements routes for questions --- config/routes.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 793a97f42..2e0283152 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -86,7 +86,9 @@ Rails.application.routes.draw do end resources :polls, only: [:show, :index] do - resources :questions, only: [:show, :index] + resources :questions, only: [] do + post :answer, on: :member + end end resources :users, only: [:show] do From 0c9e6db04d382a14f3598c1264839d797f985e17 Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:10:11 +0100 Subject: [PATCH 60/66] Implements answers in a partial --- app/controllers/polls_controller.rb | 10 +++++++--- app/views/poll/questions/_answers.html.erb | 23 ++++++++++++++++++++++ app/views/polls/show.html.erb | 12 +++++------ 3 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 app/views/poll/questions/_answers.html.erb diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index 28ce9c447..9c83bc3e3 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -9,10 +9,14 @@ class PollsController < ApplicationController end def show - questions = @poll.questions.sort_for_list.for_render + @answerable_questions = @poll.questions.answerable_by(current_user).for_render.sort_for_list + @non_answerable_questions = @poll.questions.where.not(id: @answerable_questions.map(&:id)).for_render.sort_for_list - @answerable_questions = questions.answerable_by(current_user) - @non_answerable_questions = questions.where.not(id: @answerable_questions.pluck(:id)) + @answers_by_question_id = {} + poll_partial_results = Poll::PartialResult.by_question(@poll.question_ids).by_author(current_user.try(:id)) + poll_partial_results.each do |result| + @answers_by_question_id[result.question_id] = result.answer + end end end diff --git a/app/views/poll/questions/_answers.html.erb b/app/views/poll/questions/_answers.html.erb new file mode 100644 index 000000000..94eed7045 --- /dev/null +++ b/app/views/poll/questions/_answers.html.erb @@ -0,0 +1,23 @@ +
    + <% if can? :answer, question %> +
    + <% question.valid_answers.each do |answer| %> + <% if @answers_by_question_id[question.id] == answer %> + + <%= answer %> + + <% else %> + <%= link_to answer, + answer_poll_question_path(poll_id: question.poll_id, question_id: question.id, answer: answer), + method: :post, + remote: true, + class: "button secondary hollow" %> + <% end %> + <% end %> +
    + <% else %> + <% question.valid_answers.each do |answer| %> + <%= answer %> + <% end %> + <% end %> +
    diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index a51f280fb..6282b112f 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -29,9 +29,9 @@
    <%= question.title %> - <% question.valid_answers.each do |valid_answer| %> - <%= link_to valid_answer %> - <% end %> +
    + <%= render 'poll/questions/answers', question: question %> +
    <% end %> @@ -46,8 +46,8 @@
    <%= question.title %> - <% question.valid_answers.each do |valid_answer| %> - <%= valid_answer %> - <% end %> +
    + <%= render 'poll/questions/answers', question: question %> +
    <% end %> From 11a98dce07124be18a6ca1062234dfabcde406bd Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:10:36 +0100 Subject: [PATCH 61/66] Refactors in poll/question model --- app/models/poll/question.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index ae90ada12..d56990f17 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -9,6 +9,7 @@ class Poll::Question < ActiveRecord::Base has_many :comments, as: :commentable has_many :answers + has_many :partial_results has_and_belongs_to_many :geozones belongs_to :proposal @@ -21,7 +22,7 @@ class Poll::Question < ActiveRecord::Base validates :description, length: { maximum: Poll::Question.description_max_length } validates :question, length: { in: 10..Poll::Question.question_max_length } - scope :sort_for_list, -> { order('proposal_id IS NULL', :created_at)} + scope :sort_for_list, -> { order('poll_questions.proposal_id IS NULL', :created_at)} scope :for_render, -> { includes(:author, :proposal) } scope :by_geozone, -> (geozone_id) { joins(:geozones).where(geozones: {id: geozone_id}) } From 219e139efb9b129ca0f0521081bd2afb8d74ea52 Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:10:56 +0100 Subject: [PATCH 62/66] Adds poll_partial_result factory --- app/controllers/polls/questions_controller.rb | 17 +++++++++++++++++ spec/factories.rb | 7 +++++++ 2 files changed, 24 insertions(+) create mode 100644 app/controllers/polls/questions_controller.rb diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb new file mode 100644 index 000000000..bebb7ab4a --- /dev/null +++ b/app/controllers/polls/questions_controller.rb @@ -0,0 +1,17 @@ +class Polls::QuestionsController < ApplicationController + + load_and_authorize_resource :poll + load_and_authorize_resource :question, through: :poll + + def answer + partial_result = @question.partial_results.find_or_initialize_by(author: current_user, + amount: 1, + origin: 'web') + + partial_result.answer = params[:answer] + partial_result.save! + + @answers_by_question_id = {@question.id => params[:answer]} + end + +end diff --git a/spec/factories.rb b/spec/factories.rb index 219334b85..78c6241d5 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -319,6 +319,13 @@ FactoryGirl.define do valid_answers { Faker::Lorem.words(3).join(', ') } end + factory :poll_partial_result, class: 'Poll::PartialResult' do + association :question, factory: :poll_question + association :author, factory: :user + origin { 'web' } + answer { question.verified_answers.sample } + end + factory :organization do user responsible_name "Johnny Utah" From e5e3fe32dad319e28bc714807d2a96ed76301f17 Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:11:18 +0100 Subject: [PATCH 63/66] Removes save_and_open_page from spec --- spec/features/polls_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index f44ccfd94..4276c91f0 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -152,7 +152,6 @@ feature 'Polls' do create(:poll_question, poll: poll, all_geozones: true, valid_answers: 'Han Solo, Chewbacca') login_as(create(:user, :level_two, geozone: geozone)) visit poll_path(poll) - save_and_open_page expect(page).to have_link('Han Solo') expect(page).to have_link('Chewbacca') From 38efad77f31995a012a88c945ea18e0a67d66f89 Mon Sep 17 00:00:00 2001 From: kikito Date: Fri, 11 Nov 2016 19:11:53 +0100 Subject: [PATCH 64/66] Changes the way question#copy_attributes_from_proposal works --- app/models/poll/question.rb | 6 ++++-- config/locales/en.yml | 2 ++ spec/models/poll/question_spec.rb | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index d56990f17..13245c384 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -43,7 +43,8 @@ class Poll::Question < ActiveRecord::Base self.description = proposal.description self.summary = proposal.summary self.question = proposal.question - self.geozones = Geozone.all + self.all_geozones = true + self.valid_answers = I18n.t('poll_questions.default_valid_answers') end end @@ -56,9 +57,10 @@ class Poll::Question < ActiveRecord::Base where(poll_id: Poll.answerable_by(user).pluck(:id)) .joins('LEFT OUTER JOIN "geozones_poll_questions" ON "geozones_poll_questions"."question_id" = "poll_questions"."id"') - .where('(poll_questions.all_geozones = ? or geozones_poll_questions.geozone_id = ?)', + .where('(poll_questions.all_geozones = ? OR geozones_poll_questions.geozone_id = ?)', true, user.geozone_id || -1) # user.geozone_id can be nil, which would throw errors on sql + .distinct end end diff --git a/config/locales/en.yml b/config/locales/en.yml index b032b5805..7c9abd2b9 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -385,6 +385,8 @@ en: cant_answer_incoming: "This poll has not yet started." cant_answer_expired: "This poll has finished." cant_answer_wrong_geozone: "The following questions are not available in your geozone." + poll_questions: + default_valid_answers: "Yes, No" proposal_ballots: title: "Votings" description_html: "The following citizen proposals that have reached the required supports and will be voted." diff --git a/spec/models/poll/question_spec.rb b/spec/models/poll/question_spec.rb index 92e019027..6cb38d023 100644 --- a/spec/models/poll/question_spec.rb +++ b/spec/models/poll/question_spec.rb @@ -15,12 +15,13 @@ RSpec.describe Poll::Question, type: :model do p = create(:proposal) q = create(:poll_question) q.copy_attributes_from_proposal(p) + expect(q.valid_answers).to eq(['Yes', 'No']) expect(q.author).to eq(p.author) expect(q.author_visible_name).to eq(p.author.name) expect(q.proposal_id).to eq(p.id) expect(q.title).to eq(p.title) expect(q.question).to eq(p.question) - expect(q.geozones).to eq(Geozone.all) + expect(q.all_geozones).to be_true end end From 598b1b9c012979e819ca5b6ae1c5749d03726267 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 14 Nov 2016 13:35:23 +0100 Subject: [PATCH 65/66] Adds group by to answerable_by scope to avoid duplicates --- app/models/poll/question.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index 13245c384..68f0be910 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -55,12 +55,12 @@ class Poll::Question < ActiveRecord::Base def self.answerable_by(user) return none if user.nil? || user.unverified? - where(poll_id: Poll.answerable_by(user).pluck(:id)) - .joins('LEFT OUTER JOIN "geozones_poll_questions" ON "geozones_poll_questions"."question_id" = "poll_questions"."id"') - .where('(poll_questions.all_geozones = ? OR geozones_poll_questions.geozone_id = ?)', - true, - user.geozone_id || -1) # user.geozone_id can be nil, which would throw errors on sql - .distinct + joins('LEFT JOIN "geozones_poll_questions" ON "geozones_poll_questions"."question_id" = "poll_questions"."id"') + .where('poll_questions.poll_id IN (?) AND (poll_questions.all_geozones = ? OR geozones_poll_questions.geozone_id = ?)', + Poll.answerable_by(user).pluck(:id), + true, + user.geozone_id || -1) # user.geozone_id can be nil, which would throw errors on sql + .group('poll_questions.id') end end From 1f9945d0aac761e0591302e5e401df7b91a02264 Mon Sep 17 00:00:00 2001 From: kikito Date: Mon, 14 Nov 2016 13:36:00 +0100 Subject: [PATCH 66/66] Implements answering questions --- app/controllers/polls/questions_controller.rb | 2 +- app/views/{poll => polls}/questions/_answers.html.erb | 2 +- app/views/polls/questions/answer.js.erb | 1 + app/views/polls/show.html.erb | 4 ++-- config/routes.rb | 2 +- spec/features/polls_spec.rb | 6 +++--- 6 files changed, 9 insertions(+), 8 deletions(-) rename app/views/{poll => polls}/questions/_answers.html.erb (94%) create mode 100644 app/views/polls/questions/answer.js.erb diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb index bebb7ab4a..dcf459485 100644 --- a/app/controllers/polls/questions_controller.rb +++ b/app/controllers/polls/questions_controller.rb @@ -1,7 +1,7 @@ class Polls::QuestionsController < ApplicationController load_and_authorize_resource :poll - load_and_authorize_resource :question, through: :poll + load_and_authorize_resource :question, class: 'Poll::Question', through: :poll def answer partial_result = @question.partial_results.find_or_initialize_by(author: current_user, diff --git a/app/views/poll/questions/_answers.html.erb b/app/views/polls/questions/_answers.html.erb similarity index 94% rename from app/views/poll/questions/_answers.html.erb rename to app/views/polls/questions/_answers.html.erb index 94eed7045..ee76706fc 100644 --- a/app/views/poll/questions/_answers.html.erb +++ b/app/views/polls/questions/_answers.html.erb @@ -8,7 +8,7 @@ <% else %> <%= link_to answer, - answer_poll_question_path(poll_id: question.poll_id, question_id: question.id, answer: answer), + answer_poll_question_path(poll_id: question.poll_id, id: question.id, answer: answer), method: :post, remote: true, class: "button secondary hollow" %> diff --git a/app/views/polls/questions/answer.js.erb b/app/views/polls/questions/answer.js.erb new file mode 100644 index 000000000..aabbd8d89 --- /dev/null +++ b/app/views/polls/questions/answer.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id(@question) %>_answers").html('<%= j render("polls/questions/answers", question: @question) %>'); diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index 6282b112f..ad7818a78 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -30,7 +30,7 @@ <%= question.title %>
    - <%= render 'poll/questions/answers', question: question %> + <%= render 'polls/questions/answers', question: question %>
    <% end %> @@ -47,7 +47,7 @@ <%= question.title %>
    - <%= render 'poll/questions/answers', question: question %> + <%= render 'polls/questions/answers', question: question %>
  • <% end %> diff --git a/config/routes.rb b/config/routes.rb index 2e0283152..95e5a87b1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -86,7 +86,7 @@ Rails.application.routes.draw do end resources :polls, only: [:show, :index] do - resources :questions, only: [] do + resources :questions, only: [], controller: 'polls/questions' do post :answer, on: :member end end diff --git a/spec/features/polls_spec.rb b/spec/features/polls_spec.rb index 4276c91f0..9270d5696 100644 --- a/spec/features/polls_spec.rb +++ b/spec/features/polls_spec.rb @@ -157,10 +157,10 @@ feature 'Polls' do expect(page).to have_link('Chewbacca') end - xscenario 'Level 2 users who have already answered' do + scenario 'Level 2 users who have already answered' do question = create(:poll_question, poll: poll, geozone_ids:[geozone.id], valid_answers: 'Han Solo, Chewbacca') user = create(:user, :level_two, geozone: geozone) - create(:question_answer, question: question, author: user, answer: 'Chewbacca') + create(:poll_partial_result, question: question, author: user, answer: 'Chewbacca') login_as user visit poll_path(poll) @@ -169,7 +169,7 @@ feature 'Polls' do expect(page).to have_content('Chewbacca') end - xscenario 'Level 2 users answering', :js do + scenario 'Level 2 users answering', :js do create(:poll_question, poll: poll, geozone_ids: [geozone.id], valid_answers: 'Han Solo, Chewbacca') user = create(:user, :level_two, geozone: geozone) login_as user