effective_polls 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/admin/polls_controller.rb +1 -7
  3. data/app/controllers/effective/ballots_controller.rb +4 -1
  4. data/app/datatables/admin/effective_poll_notifications_datatable.rb +4 -1
  5. data/app/datatables/admin/effective_poll_results_datatable.rb +1 -4
  6. data/app/datatables/admin/effective_polls_datatable.rb +1 -0
  7. data/app/datatables/{effective_polls_datatable.rb → effective_polls_available_polls_datatable.rb} +6 -4
  8. data/app/helpers/effective_polls_helper.rb +17 -13
  9. data/app/mailers/effective/polls_mailer.rb +3 -1
  10. data/app/models/concerns/effective_polls_user.rb +67 -0
  11. data/app/models/effective/ballot.rb +11 -2
  12. data/app/models/effective/ballot_response.rb +1 -1
  13. data/app/models/effective/poll.rb +39 -26
  14. data/app/models/effective/poll_notification.rb +2 -2
  15. data/app/models/effective/poll_question.rb +1 -1
  16. data/app/models/effective/poll_question_option.rb +1 -1
  17. data/app/views/admin/poll_notifications/_form.html.haml +3 -5
  18. data/app/views/admin/poll_questions/_form.html.haml +12 -5
  19. data/app/views/admin/polls/_form.html.haml +10 -5
  20. data/app/views/admin/polls/_form_content.html.haml +16 -20
  21. data/app/views/admin/polls/_form_poll.html.haml +16 -7
  22. data/app/views/admin/polls/_poll.html.haml +5 -0
  23. data/app/views/effective/ballots/_content.html.haml +10 -0
  24. data/app/views/effective/ballots/_layout.html.haml +3 -0
  25. data/app/views/effective/ballots/complete.html.haml +13 -8
  26. data/app/views/effective/ballots/start.html.haml +29 -12
  27. data/app/views/effective/ballots/submit.html.haml +10 -13
  28. data/app/views/effective/ballots/vote.html.haml +10 -15
  29. data/app/views/effective/poll_results/_results.html.haml +2 -2
  30. data/app/views/effective/polls/_dashboard.html.haml +25 -0
  31. data/app/views/effective/polls_mailer/poll_before_poll_ends.liquid +0 -1
  32. data/app/views/effective/polls_mailer/poll_reminder.liquid +0 -1
  33. data/app/views/effective/polls_mailer/poll_upcoming_reminder.liquid +0 -1
  34. data/app/views/effective/polls_mailer/poll_when_poll_ends.liquid +0 -1
  35. data/app/views/effective/polls_mailer/poll_when_poll_starts.liquid +0 -1
  36. data/config/effective_polls.rb +2 -11
  37. data/config/locales/effective_polls.yml +14 -0
  38. data/config/routes.rb +2 -5
  39. data/db/migrate/101_create_effective_polls.rb +12 -10
  40. data/db/seeds.rb +2 -1
  41. data/lib/effective_polls/engine.rb +7 -0
  42. data/lib/effective_polls/version.rb +1 -1
  43. data/lib/effective_polls.rb +2 -4
  44. data/lib/tasks/effective_polls_tasks.rake +23 -12
  45. metadata +9 -4
  46. data/app/views/admin/polls/results.html.haml +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '092395996d087f516aca9b5aa9f42e170c56702b0dd9c7c7479332cb18a0c2c7'
4
- data.tar.gz: 316a9df7d201ed389316f1cc11c5a77310038957520bdaf711666bfcf867ed7a
3
+ metadata.gz: 637320f25a72489ada773806629e70590bb5c8435e871a6de40497e2eb6300ed
4
+ data.tar.gz: e797d1afdad6be66099b291ec7a809cbb65ef32d7963ca04f03d3ac3d91fe2a9
5
5
  SHA512:
6
- metadata.gz: d4f8a181881338bd4f274194770d82fb632f0456910d1df843ec404025d4eaceb219fca21215e70d44c278a6f1791dff199fbab9b3cd2f6e88fadc6498fbfa7a
7
- data.tar.gz: 7dae7c572c9236edcae987f7d3a4e1afce6cd65557890a82c81797b7a7d12816157020d0966379c3f70322d08ffdc7a0bde593c755ffe824153e3a97a4be3a4f
6
+ metadata.gz: 7317013d4063bdd11eaf4a72b6d5ca964c7acb2c35ac29653e9c7043c4e4c40de4e1b4b55079ed023b758f08982a51ca17926e37c5abafbca2462cf0b4a9e657
7
+ data.tar.gz: d3fe9a3b04a9ca98c5a27fa956fb82d536db6b9662b6d61a0e8fd954f603673384f6d70c3ec33e51fabde548063b126892508e858be72e616d2c9ff30318e732
@@ -5,13 +5,7 @@ module Admin
5
5
 
6
6
  include Effective::CrudController
7
7
 
8
- def results
9
- @poll = Effective::Poll.find(params[:id])
10
- EffectiveResources.authorize!(self, :results, @poll)
11
-
12
- @datatable = Admin::EffectivePollResultsDatatable.new(poll_token: @poll.token)
13
- @page_title = "#{@poll} Results"
14
- end
8
+ on :save, only: :create, redirect: :edit
15
9
 
16
10
  def permitted_params
17
11
  params.require(:effective_poll).permit!
@@ -1,6 +1,9 @@
1
1
  module Effective
2
2
  class BallotsController < ApplicationController
3
- before_action(:authenticate_user!) if defined?(Devise)
3
+
4
+ if defined?(Devise)
5
+ before_action :authenticate_user!, unless: -> { action_name == 'new' || (action_name == 'show' && params[:id] == 'start') }
6
+ end
4
7
 
5
8
  include Effective::WizardController
6
9
 
@@ -31,7 +31,10 @@ class Admin::EffectivePollNotificationsDatatable < Effective::Datatable
31
31
  end
32
32
 
33
33
  col :subject
34
- col :body
34
+
35
+ col :body do |notification|
36
+ simple_format(notification.body.to_s)
37
+ end
35
38
 
36
39
  col :started_at, visible: false
37
40
  col :completed_at
@@ -41,10 +41,7 @@ class Admin::EffectivePollResultsDatatable < Effective::Datatable
41
41
  end
42
42
 
43
43
  def poll
44
- @poll ||= begin
45
- raise('expected datatable poll_token attribute') unless attributes[:poll_token]
46
- Effective::Poll.deep_results.find(attributes[:poll_token])
47
- end
44
+ @poll ||= Effective::Poll.deep_results.where(id: attributes[:poll_id]).first!
48
45
  end
49
46
 
50
47
  end
@@ -18,6 +18,7 @@ class Admin::EffectivePollsDatatable < Effective::Datatable
18
18
  col :end_at
19
19
  col :audience
20
20
 
21
+ col :poll_notifications
21
22
  col :poll_questions, visible: false
22
23
 
23
24
  actions_col
@@ -1,13 +1,14 @@
1
+ # Dashboard available polls
1
2
  # Displays available polls that the current_user may complete
2
3
 
3
- class EffectivePollsDatatable < Effective::Datatable
4
+ class EffectivePollsAvailablePollsDatatable < Effective::Datatable
4
5
  datatable do
5
6
  order :start_at
6
7
 
7
8
  col :start_at, visible: false
8
9
 
9
10
  col :title
10
- col :available_date, label: 'Date'
11
+ col :available_date
11
12
 
12
13
  actions_col(actions: []) do |poll|
13
14
  ballot = poll.ballots.where(user: current_user).first
@@ -15,16 +16,17 @@ class EffectivePollsDatatable < Effective::Datatable
15
16
  if ballot.blank?
16
17
  dropdown_link_to('Start', effective_polls.poll_ballot_build_path(poll, :new, :start))
17
18
  elsif ballot.completed?
19
+ #dropdown_link_to('Show', effective_polls.poll_ballot_path(poll, ballot))
18
20
  'Complete'
19
21
  else
20
22
  dropdown_link_to('Continue', effective_polls.poll_ballot_build_path(poll, ballot, ballot.next_step))
23
+ dropdown_link_to('Delete', effective_polls.poll_ballot_path(poll, ballot), 'data-confirm': "Really delete #{ballot}?", 'data-method': :delete)
21
24
  end
22
25
  end
23
26
  end
24
27
 
25
28
  collection do
26
- raise('expected a current_user') unless current_user.present?
27
- Effective::Poll.available.select { |poll| poll.available_for?(current_user) }
29
+ Effective::Poll.where(id: current_user.available_polls)
28
30
  end
29
31
 
30
32
  end
@@ -1,22 +1,26 @@
1
1
  module EffectivePollsHelper
2
2
 
3
+ # Used on dashboard
4
+ def polls_name_label
5
+ et('effective_polls.name')
6
+ end
7
+
3
8
  # Used by admin/polls form
4
- def effective_polls_audience_scope_collection
5
- # Normalize the collection into [[label, value], [label, value]]
6
- scopes = Array(EffectivePolls.audience_user_scopes).map do |key, value|
7
- (key.present? && value.present?) ? [key, value] : [key.to_s.titleize, key]
8
- end
9
+ def effective_polls_audience_scope_collection(poll)
10
+ klass = poll.try(:audience_class)
11
+ raise('expected a poll with an audience_class') unless klass.try(:effective_polls_user?)
9
12
 
10
- # Makes sure the User model responds to all values
11
- scopes.each do |_, scope|
12
- unless defined?(User) && User.respond_to?(scope)
13
- raise("invalid effective_polls config.audience_user_scopes value. The user model must respond to the scope User.#{scope}")
14
- end
15
- end
13
+ resource = klass.new
14
+
15
+ scopes = resource.poll_audience_scopes
16
+ raise('expected poll audience scopes') unless scopes.kind_of?(Array)
16
17
 
17
18
  # Append the number of users in this scope
18
- scopes.map! do |label, scope|
19
- ["#{label} (#{pluralize(User.send(scope).count, 'user')})", scope]
19
+ scopes.map do |label, scope|
20
+ relation = resource.poll_audience_scope(scope)
21
+ raise("invalid poll_audience_scope for #{scope}") unless relation.kind_of?(ActiveRecord::Relation)
22
+
23
+ ["#{label} (#{pluralize(relation.count, 'user')})", scope]
20
24
  end
21
25
  end
22
26
 
@@ -75,7 +75,9 @@ module Effective
75
75
  title: poll.title,
76
76
  url: effective_polls.poll_url(poll),
77
77
  user: {
78
- name: user.to_s,
78
+ name: (user.try(:email_to_s) || user.to_s),
79
+ first_name: user.try(:first_name).to_s,
80
+ last_name: user.try(:last_name).to_s,
79
81
  email: user.email
80
82
  }
81
83
  }
@@ -0,0 +1,67 @@
1
+ # EffectivePollsUser
2
+ #
3
+ # Mark your user model with effective_polls_user to get all the includes
4
+
5
+ module EffectivePollsUser
6
+ extend ActiveSupport::Concern
7
+
8
+ module Base
9
+ def effective_polls_user
10
+ include ::EffectivePollsUser
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ def effective_polls_user?; true; end
16
+ end
17
+
18
+ included do
19
+ has_many :ballots, -> { Effective::Ballot.sorted }, inverse_of: :user, as: :user, class_name: 'Effective::Ballot'
20
+ end
21
+
22
+ # The list of all available audience scopes for the Poll Selected Users
23
+ def poll_audience_scopes
24
+ scopes = [
25
+ ['All Users', :all]
26
+ ]
27
+
28
+ if self.class.try(:effective_memberships_user?)
29
+ scopes += [
30
+ ['All members', :members],
31
+ ['All removed members', :membership_removed],
32
+ ['All members in good standing', :membership_in_good_standing],
33
+ ['All members not in good standing', :membership_not_in_good_standing],
34
+ ['All members renewed this period', :membership_renewed_this_period],
35
+ ]
36
+
37
+ scopes += EffectiveMemberships.Category.sorted.map do |category|
38
+ ["All #{category} members", "members_with_category_id_#{category.id}"]
39
+ end
40
+ end
41
+
42
+ scopes
43
+ end
44
+
45
+ # Turns the given audience_scope value into the actual ActiveRecord::Relation scope
46
+ def poll_audience_scope(value)
47
+ collection = self.class.respond_to?(:unarchived) ? self.class.unarchived : self.class
48
+
49
+ # If we respond to the fill value, call it
50
+ return collection.send(value) if collection.respond_to?(value)
51
+
52
+ # Parse the value
53
+ name, id = value.to_s.split('_id_')
54
+
55
+ case name.try(:to_sym)
56
+ when :members_with_category
57
+ collection.members_with_category(EffectiveMemberships.Category.find(id))
58
+ else
59
+ raise("unknown poll_audience_scope for #{value}")
60
+ end
61
+ end
62
+
63
+ def available_polls
64
+ Effective::Poll.available.select { |poll| poll.available_for?(self) }
65
+ end
66
+
67
+ end
@@ -3,14 +3,19 @@ module Effective
3
3
  attr_accessor :current_user
4
4
  attr_accessor :current_step
5
5
 
6
+ # Application namespace
7
+ belongs_to :user, polymorphic: true
8
+
9
+ # Effective namespace
6
10
  belongs_to :poll
7
- belongs_to :user
8
11
 
9
12
  has_many :ballot_responses, dependent: :destroy
10
13
  accepts_nested_attributes_for :ballot_responses
11
14
 
12
15
  acts_as_tokened
13
16
 
17
+ log_changes(to: :poll) if respond_to?(:log_changes)
18
+
14
19
  acts_as_wizard(
15
20
  start: 'Start',
16
21
  vote: 'Ballot',
@@ -34,6 +39,10 @@ module Effective
34
39
 
35
40
  scope :deep, -> { includes(:poll, :user, ballot_responses: [:poll, :poll_question, :poll_question_options]) }
36
41
  scope :sorted, -> { order(:id) }
42
+
43
+ scope :in_progress, -> { where(completed_at: nil) }
44
+ scope :done, -> { where.not(completed_at: nil) }
45
+
37
46
  scope :completed, -> { where.not(completed_at: nil) }
38
47
 
39
48
  before_validation(if: -> { new_record? }) do
@@ -48,7 +57,7 @@ module Effective
48
57
  validates :ballot_responses, associated: true
49
58
 
50
59
  def to_s
51
- 'ballot'
60
+ model_name.human
52
61
  end
53
62
 
54
63
  # Find or build
@@ -64,7 +64,7 @@ module Effective
64
64
  length: { maximum: 5, message: 'please select 5 options or fewer' }
65
65
 
66
66
  def to_s
67
- 'ballot reponse'
67
+ model_name.human
68
68
  end
69
69
 
70
70
  def response
@@ -1,10 +1,6 @@
1
1
  module Effective
2
2
  class Poll < ActiveRecord::Base
3
- has_rich_text :all_steps_content
4
- has_rich_text :start_content
5
- has_rich_text :vote_content
6
- has_rich_text :submit_content
7
- has_rich_text :complete_content
3
+ acts_as_tokened
8
4
 
9
5
  has_many :poll_notifications, -> { order(:id) }, inverse_of: :poll, dependent: :destroy
10
6
  accepts_nested_attributes_for :poll_notifications, allow_destroy: true
@@ -19,7 +15,12 @@ module Effective
19
15
  has_many :completed_ballots, -> { Effective::Ballot.completed }, class_name: 'Effective::Ballot'
20
16
  has_many :completed_ballot_responses, -> { where(ballot: Effective::Ballot.completed) }, class_name: 'Effective::BallotResponse'
21
17
 
22
- acts_as_tokened
18
+ has_many_rich_texts
19
+ # rich_text_all_steps_content
20
+ # rich_text_start_content
21
+ # rich_text_vote_content
22
+ # rich_text_submit_content
23
+ # rich_text_complete_content
23
24
 
24
25
  if respond_to?(:log_changes)
25
26
  log_changes(except: [:ballots, :ballot_responses, :completed_ballots, :completed_ballot_responses])
@@ -29,29 +30,23 @@ module Effective
29
30
 
30
31
  effective_resource do
31
32
  # Acts as tokened
32
- token :string, permitted: false
33
+ token :string, permitted: false
33
34
 
34
35
  title :string
35
36
 
36
37
  start_at :datetime
37
38
  end_at :datetime
38
39
 
39
- audience :string
40
- audience_scope :text # An Array of user_ids or named scopes on the User model
40
+ audience :string
41
+ audience_class_name :string
42
+ audience_scope :text # An Array of user_ids or named scopes on the User model
41
43
 
42
44
  timestamps
43
45
  end
44
46
 
45
47
  serialize :audience_scope, Array
46
48
 
47
- scope :deep, -> {
48
- includes(poll_questions: :poll_question_options)
49
- .with_rich_text_all_steps_content
50
- .with_rich_text_start_content
51
- .with_rich_text_vote_content
52
- .with_rich_text_submit_content
53
- .with_rich_text_complete_content
54
- }
49
+ scope :deep, -> { includes(poll_questions: :poll_question_options) }
55
50
 
56
51
  scope :deep_results, -> {
57
52
  includes(poll_questions: :poll_question_options)
@@ -68,6 +63,8 @@ module Effective
68
63
  validates :start_at, presence: true
69
64
 
70
65
  validates :audience, inclusion: { in: AUDIENCES }
66
+ validates :audience_class_name, presence: true
67
+
71
68
  validates :audience_scope, presence: true, unless: -> { audience == 'All Users' }
72
69
 
73
70
  validate(if: -> { start_at.present? && end_at.present? }) do
@@ -75,33 +72,49 @@ module Effective
75
72
  end
76
73
 
77
74
  def to_s
78
- title.presence || 'New Poll'
75
+ title.presence || model_name.human
79
76
  end
80
77
 
81
78
  def available_for?(user)
82
- raise('expected a user') unless user.kind_of?(User)
79
+ raise('expected an effective_polls_user') unless user.class.try(:effective_polls_user?)
83
80
  available? && users.include?(user)
84
81
  end
85
82
 
83
+ def audience_class
84
+ klass = audience_class_name.safe_constantize
85
+ raise('expected an effective_polls_user klass') unless klass.try(:effective_polls_user?)
86
+ klass
87
+ end
88
+
86
89
  def users(except_completed: false)
90
+ klass = audience_class()
91
+ resource = klass.new
92
+
87
93
  users = case audience
88
94
  when 'All Users'
89
- User.all
95
+ klass.try(:unarchived) || klass.all
90
96
  when 'Individual Users'
91
- User.where(id: audience_scope)
97
+ (klass.try(:unarchived) || klass.all).where(id: audience_scope)
92
98
  when 'Selected Users'
93
- collection = User.none
94
- audience_scope.each { |scope| collection = collection.or(User.send(scope)) }
99
+ collection = klass.none
100
+
101
+ audience_scope.each do |scope|
102
+ relation = resource.poll_audience_scope(scope)
103
+ raise("invalid poll_audience_scope for #{scope}") unless relation.kind_of?(ActiveRecord::Relation)
104
+
105
+ collection = collection.or(relation)
106
+ end
107
+
95
108
  collection
96
109
  else
97
110
  raise('unexpected audience')
98
111
  end
99
112
 
100
113
  if except_completed
101
- users.where.not(id: completed_ballots.select('user_id as id'))
102
- else
103
- users
114
+ users = users.where.not(id: completed_ballots.select('user_id as id'))
104
115
  end
116
+
117
+ users
105
118
  end
106
119
 
107
120
  def available?
@@ -72,7 +72,7 @@ module Effective
72
72
  validates :subject, presence: true
73
73
  validates :body, presence: true
74
74
 
75
- if EffectivePolls.use_effective_email_templates
75
+ with_options(if: -> { EffectivePolls.use_effective_email_templates }) do
76
76
  validates :body, liquid: true
77
77
  validates :subject, liquid: true
78
78
  end
@@ -81,7 +81,7 @@ module Effective
81
81
  presence: true, uniqueness: { scope: [:poll_id, :category], message: 'already exists' }
82
82
 
83
83
  def to_s
84
- 'poll notification'
84
+ [category.presence, subject.presence].compact.join(' - ') || model_name.human
85
85
  end
86
86
 
87
87
  def email_template
@@ -62,7 +62,7 @@ module Effective
62
62
  end
63
63
 
64
64
  def to_s
65
- title.presence || 'New Poll Question'
65
+ title.presence || model_name.human
66
66
  end
67
67
 
68
68
  def poll_question_option?
@@ -19,7 +19,7 @@ module Effective
19
19
  validates :position, presence: true
20
20
 
21
21
  def to_s
22
- title.presence || 'New Poll Question Option'
22
+ title.presence || model_name.human
23
23
  end
24
24
 
25
25
  end
@@ -12,22 +12,20 @@
12
12
  - template = 'poll_' + category.parameterize.underscore
13
13
 
14
14
  = f.show_if :category, category do
15
- = render "/admin/poll_notifications/form_#{template}", f: f
15
+ .my-3= render "/admin/poll_notifications/form_#{template}", f: f
16
+
17
+ = f.select :from, EffectivePolls.mailer_froms
16
18
 
17
19
  - if f.object.category == category
18
- = f.email_field :from
19
20
  = f.text_field :subject
20
21
  = f.text_area :body, rows: 10
21
22
 
22
23
  - elsif EffectivePolls.use_effective_email_templates == false
23
- = f.email_field :from, value: EffectivePolls.mailer[:default_from]
24
24
  = f.text_field :subject, value: ''
25
25
  = f.text_area :body, rows: 10, value: ''
26
26
 
27
27
  - else
28
28
  - email_template = Effective::EmailTemplate.where(template_name: template).first!
29
-
30
- = f.email_field :from, value: email_template.from
31
29
  = f.text_field :subject, value: email_template.subject
32
30
  = f.text_area :body, rows: 10, value: email_template.body
33
31
 
@@ -2,19 +2,26 @@
2
2
  - if inline_datatable?
3
3
  = f.hidden_field :poll_id
4
4
  - else
5
- = f.select :poll_id, Effective::Poll.sorted.editable.all
5
+ = f.select :poll_id, Effective::Poll.all
6
6
 
7
7
  = f.text_field :title, label: 'Question Title'
8
- = f.rich_text_area :body, label: 'Body (optional)'
8
+
9
+ - if defined?(EffectiveArticleEditor)
10
+ = f.article_editor :body, label: 'Body (optional)'
11
+ - else
12
+ = f.rich_text_area :body, label: 'Body (optional)'
9
13
 
10
14
  = f.check_box :required, hint: 'A response to this question will be required'
11
15
  = f.select :category, Effective::PollQuestion::CATEGORIES
12
16
 
13
17
  = f.show_if :category, 'Choose one' do
14
- .card
18
+ .mt-3.card
15
19
  .card-body
16
- %h5 Choose one
17
- %p Display radio buttons to choose one option
20
+ %h5 Options
21
+ %p Display the following options:
22
+
23
+ = f.has_many :poll_question_options, build: true do |fa|
24
+ = fa.text_field :title, label: false
18
25
 
19
26
  = f.show_if :category, 'Select all that apply' do
20
27
  .card
@@ -7,18 +7,23 @@
7
7
  = render 'admin/polls/form_content', poll: poll
8
8
 
9
9
  = tab 'Questions' do
10
- - datatable = Admin::EffectivePollQuestionsDatatable.new(poll_id: poll.id)
10
+ - datatable = Admin::EffectivePollQuestionsDatatable.new(poll: poll)
11
11
  = render_datatable(datatable, inline: true, simple: true)
12
12
 
13
13
  = tab 'Notifications' do
14
14
  %p
15
15
  The following email notifications will be sent to
16
- = pluralize(poll.users.count, 'users')
16
+ = pluralize(poll.users.count, 'user')
17
17
  in the audience.
18
18
 
19
- - datatable = Admin::EffectivePollNotificationsDatatable.new(poll_id: poll.id)
19
+ %p
20
+ The url for this #{et(poll)} is:
21
+ - url = effective_polls.poll_url(poll)
22
+ = link_to(url, url, target: '_blank')
23
+
24
+ - datatable = Admin::EffectivePollNotificationsDatatable.new(poll: poll)
20
25
  = render_datatable(datatable, inline: true, simple: true)
21
26
 
22
- - if poll.respond_to?(:log_changes_datatable)
27
+ - if poll.respond_to?(:logs_datatable)
23
28
  = tab 'Logs' do
24
- = render_datatable(poll.log_changes_datatable)
29
+ = render_datatable(poll.logs_datatable)
@@ -1,27 +1,23 @@
1
+ %p Each of the following content areas will be displayed on the ballot wizard.
2
+
1
3
  = effective_form_with(model: [:admin, poll], engine: true) do |f|
2
- .card.mb-4
3
- .card-body
4
- %h5.card-title All Steps Content
5
- = f.rich_text_area :all_steps_content, label: false, hint: 'displayed on all ballot steps'
4
+ = card("All Steps") do
5
+ - if defined?(EffectiveArticleEditor)
6
+ = f.article_editor "rich_text_all_steps_content", label: false, hint: "displayed on all steps"
7
+ - else
8
+ = f.rich_text_area "rich_text_all_steps_content", label: false, hint: "displayed on all steps"
6
9
 
7
- .card.mb-4
8
- .card-body
9
- %h5.card-title Start Step
10
- = f.rich_text_area :start_content, label: false, hint: 'displayed on the start step only'
10
+ %hr
11
11
 
12
- .card.mb-4
13
- .card-body
14
- %h5.card-title Vote Step
15
- = f.rich_text_area :vote_content, label: false, hint: 'displayed on the vote step only'
12
+ - enabled = Effective::Ballot.all_wizard_steps
16
13
 
17
- .card.mb-4
18
- .card-body
19
- %h5.card-title Review and Submit Step
20
- = f.rich_text_area :submit_content, label: false, hint: 'displayed on the review and submit step only'
14
+ - Effective::Ballot::WIZARD_STEPS.each do |step, title|
15
+ - next unless enabled.include?(step)
21
16
 
22
- .card.mb-4
23
- .card-body
24
- %h5.card-title Complete Step
25
- = f.rich_text_area :complete_content, label: false, hint: 'displayed on the complete step only'
17
+ = card("#{title}") do
18
+ - if defined?(EffectiveArticleEditor)
19
+ = f.article_editor "rich_text_#{step}_content", label: false, hint: "displayed on the ballot #{step} wizard step only"
20
+ - else
21
+ = f.rich_text_area "rich_text_#{step}_content", label: false, hint: "displayed on the ballot #{step} wizard step only"
26
22
 
27
23
  = f.submit
@@ -1,32 +1,41 @@
1
1
  = effective_form_with(model: [:admin, poll], engine: true) do |f|
2
+
2
3
  = f.text_field :title, hint: 'The title of your poll or election.'
3
4
 
4
- = f.datetime_field :start_at, input_js: { minDate: Time.zone.now.beginning_of_day.strftime('%F') }
5
+ = f.datetime_field :start_at
5
6
  = f.datetime_field :end_at
6
7
 
8
+ - if f.object.poll_notifications.present?
9
+ .alert.alert-info
10
+ Please be aware of the existing #{ets(f.object.poll_notifications)} when changing the start or end availability date.
11
+
7
12
  -# Audience
13
+ - f.object.audience_class_name ||= current_user.class.name
14
+
15
+ = f.hidden_field :audience_class_name
8
16
  = f.radios :audience, Effective::Poll::AUDIENCES
9
17
 
10
18
  = f.show_if :audience, 'All Users' do
11
19
  .card
12
20
  .card-body
13
21
  %h5 All Users
14
- %p All users may complete this poll
22
+ %p All users may complete this #{etd(poll)}
15
23
 
16
24
  = f.show_if :audience, 'Individual Users' do
17
25
  .card
18
26
  .card-body
19
27
  %h5 Individual Users
20
- %p Only the following individual users may complete this poll
28
+ %p Only the following individual users may complete this #{etd(poll)}
21
29
 
22
- - user_ids = User.respond_to?(:sorted) ? User.sorted : User.all
23
- = f.select :audience_scope, user_ids, multiple: true, label: false
30
+ -# Audience Users
31
+ - ajax_url = (@select2_users_ajax_path || effective_resources.users_admin_select2_ajax_index_path) unless Rails.env.test?
32
+ = f.select :audience_scope, current_user.class.all, ajax_url: ajax_url, multiple: true
24
33
 
25
34
  = f.show_if :audience, 'Selected Users' do
26
35
  .card
27
36
  .card-body
28
37
  %h5 Selected Users
29
- %p Users within any of the following groups may complete this poll
30
- = f.checks :audience_scope, effective_polls_audience_scope_collection(), multiple: true, label: false
38
+ %p Users within any of the following groups may complete this #{etd(poll)}
39
+ = f.checks :audience_scope, effective_polls_audience_scope_collection(f.object), multiple: true, label: false
31
40
 
32
41
  = effective_submit(f)
@@ -0,0 +1,5 @@
1
+ = render 'effective/poll_results/results', poll: @poll
2
+
3
+ = card('Raw Data') do
4
+ - datatable = Admin::EffectivePollResultsDatatable.new(poll: @poll)
5
+ = render_datatable(datatable)
@@ -0,0 +1,10 @@
1
+ - all_steps_content = resource.poll&.rich_text_all_steps_content
2
+ - step_content = resource.poll&.send("rich_text_#{step}_content")
3
+
4
+ - if all_steps_content.present?
5
+ .card.mb-4
6
+ .card-body= all_steps_content.to_s
7
+
8
+ - if step_content.present?
9
+ .card.mb-4
10
+ .card-body= step_content.to_s
@@ -0,0 +1,3 @@
1
+ .row
2
+ .col-lg-3.mb-3= render_wizard_sidebar(resource)
3
+ .col-lg-9= yield
@@ -1,11 +1,16 @@
1
- = render_wizard_sidebar(resource) do
2
- %h1= @page_title
1
+ = render 'layout' do
2
+ = render 'effective/ballots/content', resource: resource
3
3
 
4
- - if resource.poll.all_steps_content.present?
5
- .mb-2= resource.poll.all_steps_content
4
+ - raise('expected a completed? poll') unless resource.completed?
6
5
 
7
- - if resource.poll.complete_content.present?
8
- .mb-2= resource.poll.complete_content
6
+ .alert.alert-warning.mb-4
7
+ Successfully completed on #{resource.completed_at.strftime('%F')}.
9
8
 
10
- .text-center
11
- %p= link_to 'Home', root_path, class: 'btn btn-primary'
9
+ .mb-4
10
+ = link_to "Return to Dashboard", return_to_dashboard_path, class: 'btn btn-lg btn-primary btn-block'
11
+
12
+ = card do
13
+ %p= resource.poll
14
+ = render 'effective/ballots/ballot', ballot: resource
15
+
16
+ = link_to "Return to Dashboard", return_to_dashboard_path, class: 'btn btn-lg btn-primary btn-block'
@@ -1,17 +1,34 @@
1
- = render_wizard_sidebar(resource) do
2
- %h1= resource.poll
1
+ = render 'layout' do
2
+ = render 'effective/ballots/content', resource: resource
3
3
 
4
- .alert.alert-warning
5
- This is a <strong>Secret Ballot</strong>.
6
- Only you will know what you have submitted and no one has access to individual ballots.
4
+ - # Signed out
5
+ - if resource.user.blank?
6
+ = card do
7
+ %p Welcome!
7
8
 
8
- - if resource.poll.all_steps_content.present?
9
- .mb-2= resource.poll.all_steps_content
9
+ %p You are about to register for #{resource.poll}.
10
10
 
11
- - if resource.poll.start_content.present?
12
- .mb-2= resource.poll.start_content
11
+ %p
12
+ Please
13
+ = link_to 'sign in', '/users/sign_in'
14
+ or
15
+ = link_to 'sign up', '/users/sign_up'
16
+ to continue.
17
+
18
+ %p= link_to 'Sign In to Continue', '/users/sign_in', class: 'btn btn-primary'
13
19
 
14
- = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
15
- = f.hidden_field :current_step
20
+ - # Signed in
21
+ - if resource.user.present?
22
+ .alert.alert-warning.mb-4
23
+ This is a <strong>Secret Ballot</strong>.
24
+ Only you will know what you have submitted and no one has access to individual ballots.
16
25
 
17
- = f.submit 'Start', center: true
26
+ = card do
27
+ %p Welcome #{current_user}!
28
+
29
+ %p You are starting a #{etd(resource.poll)} for #{resource.poll}.
30
+
31
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
32
+ = f.hidden_field :current_step
33
+
34
+ = f.submit 'Start', center: true
@@ -1,17 +1,14 @@
1
- = render_wizard_sidebar(resource) do
2
- %h1= resource.poll
1
+ = render 'layout' do
2
+ = render 'effective/ballots/content', resource: resource
3
3
 
4
- - if resource.poll.all_steps_content.present?
5
- .mb-2= resource.poll.all_steps_content
4
+ = card do
5
+ %p= resource.poll
6
6
 
7
- - if resource.poll.submit_content.present?
8
- .mb-2= resource.poll.submit_content
7
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
8
+ = f.hidden_field :current_step
9
9
 
10
- = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
11
- = f.hidden_field :current_step
10
+ = render(resource)
12
11
 
13
- = render(resource)
14
-
15
- = f.submit(center: true) do
16
- = link_to 'Change Ballot', wizard_path(:vote), class: 'btn btn-secondary'
17
- = f.save 'Submit Ballot'
12
+ = f.submit(center: true) do
13
+ = link_to 'Change Ballot', wizard_path(:vote), class: 'btn btn-secondary'
14
+ = f.save 'Submit Ballot'
@@ -1,19 +1,14 @@
1
- = render_wizard_sidebar(resource) do
2
- %h1= resource.poll
1
+ = render 'layout' do
2
+ = render 'effective/ballots/content', resource: resource
3
3
 
4
- - if resource.poll.all_steps_content.present?
5
- .mb-2= resource.poll.all_steps_content
4
+ = card do
5
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
6
+ = f.hidden_field :current_step
6
7
 
7
- - if resource.poll.vote_content.present?
8
- .mb-2= resource.poll.vote_content
8
+ - resource.poll.poll_questions.deep.all.each_with_index do |poll_question, index|
9
+ - ballot_response = resource.ballot_response(poll_question)
9
10
 
10
- = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
11
- = f.hidden_field :current_step
11
+ = f.fields_for :ballot_responses, ballot_response do |fbr|
12
+ = render('/effective/ballot_responses/fields', f: fbr, poll_question: poll_question)
12
13
 
13
- - resource.poll.poll_questions.deep.all.each_with_index do |poll_question, index|
14
- - ballot_response = resource.ballot_response(poll_question)
15
-
16
- = f.fields_for :ballot_responses, ballot_response do |fbr|
17
- = render('/effective/ballot_responses/fields', f: fbr, poll_question: poll_question)
18
-
19
- = f.submit 'Save and Continue', center: true
14
+ = f.submit 'Save and Continue', center: true
@@ -6,11 +6,11 @@
6
6
 
7
7
  %p
8
8
  %strong
9
- = pluralize(poll.completed_ballots.count, 'users')
9
+ = pluralize(poll.completed_ballots.count, 'user')
10
10
  completed
11
11
  ballots from an audience of
12
12
  = succeed('.') do
13
- %strong= pluralize(poll.users.count, 'total users')
13
+ %strong= pluralize(poll.users.count, 'total user')
14
14
 
15
15
  .card.mb-3
16
16
  .card-body
@@ -0,0 +1,25 @@
1
+ -# In progress ballot
2
+ - ballot = Effective::Ballot.in_progress.where(user: current_user).first
3
+ - datatable = EffectiveResources.best('EffectivePollsAvailablePollsDatatable').new(self, namespace: :effective)
4
+
5
+ - if ballot.present?
6
+ %h2 In Progress #{et(Effective::Ballot)}
7
+
8
+ %p Your submission for #{ballot.poll} is incomplete
9
+
10
+ %p
11
+ Please
12
+ = link_to("Continue #{ballot.poll}", effective_polls.poll_ballot_build_path(ballot.poll, ballot, ballot.next_step), 'data-turbolinks' => false, class: 'btn btn-primary')
13
+ or you can
14
+ = link_to('Abandon', effective_polls.poll_ballot_path(ballot.poll, ballot), 'data-confirm': "Really delete #{ballot}?", 'data-method': :delete, class: 'btn btn-danger')
15
+ to begin again.
16
+
17
+ %hr
18
+
19
+ %h2 #{polls_name_label}
20
+
21
+ - if datatable.present?
22
+ %p The following #{etsd(Effective::Poll)} are available:
23
+ = render_datatable(datatable, simple: true)
24
+ - else
25
+ %p There are no available #{etsd(Effective::Poll)}. When there are, we'll show them here.
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  subject: 'Please submit your ballot for {{ title }}'
3
- from: 'admin@example.com'
4
3
  ---
5
4
  Hello {{ user.name }},
6
5
 
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  subject: 'Reminder - Please submit your ballot for {{ title }}'
3
- from: 'admin@example.com'
4
3
  ---
5
4
  Hello {{ user.name }},
6
5
 
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  subject: '{{ title }} is upcoming'
3
- from: 'admin@example.com'
4
3
  ---
5
4
  Hello {{ user.name }},
6
5
 
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  subject: '{{ title }} has ended'
3
- from: 'admin@example.com'
4
3
  ---
5
4
  Hello {{ user.name }},
6
5
 
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  subject: '{{ title }} has started'
3
- from: 'admin@example.com'
4
3
  ---
5
4
  Hello {{ user.name }},
6
5
 
@@ -3,19 +3,9 @@ EffectivePolls.setup do |config|
3
3
  # Configure the Layout per controller, or all at once
4
4
  # config.layout = { application: 'application', admin: 'admin' }
5
5
 
6
- # Audience Scope Collection
7
- #
8
- # When creating a new poll, an Array of User scopes can be provided
9
- # The User model must respond to these
10
- #
11
- # config.audience_user_scopes = [:all, :registered]
12
- # config.audience_user_scopes = [['All Users', :all], ['Registered Users', :registered]]
13
- #
14
- config.audience_user_scopes = [['All Users', :all]]
15
-
16
6
  # Notifications Mailer Settings
17
7
  #
18
- # Schedule rake effective_polls:notify to run every 10 minutes
8
+ # Schedule rake effective_polls:send_notifications to run every 10 minutes
19
9
  # to send out email poll notifications
20
10
  #
21
11
  # Please see config/initializers/effective_resources.rb for default effective_* gem mailer settings
@@ -29,6 +19,7 @@ EffectivePolls.setup do |config|
29
19
  # config.deliver_method = nil # The deliver method, deliver_later or deliver_now
30
20
  # config.mailer_layout = nil # Default mailer layout
31
21
  # config.mailer_sender = nil # Default From value
22
+ # config.mailer_froms = nil # Default Froms collection
32
23
  # config.mailer_admin = nil # Default To value for Admin correspondence
33
24
 
34
25
  # Use effective email templates for event notifications
@@ -0,0 +1,14 @@
1
+ en:
2
+ effective_polls:
3
+ name: 'Elections and Polls'
4
+ acronym: 'Polls'
5
+
6
+ activerecord:
7
+ models:
8
+ effective/poll: 'Poll'
9
+ effective/poll_question: 'Poll Question'
10
+ effective/poll_question_option: 'Poll Question Option'
11
+ effective/poll_notification: 'Poll Notification'
12
+ effective/ballot: 'Ballot'
13
+ effective/ballot_response: 'Ballot Response'
14
+ effective/ballot_response_option: 'Ballot Response Option'
data/config/routes.rb CHANGED
@@ -5,17 +5,14 @@ end
5
5
  EffectivePolls::Engine.routes.draw do
6
6
  scope module: 'effective' do
7
7
  resources :polls, only: [:show] do
8
- resources :ballots, only: [:new, :show] do
8
+ resources :ballots, only: [:new, :show, :destroy] do
9
9
  resources :build, controller: :ballots, only: [:show, :update]
10
10
  end
11
11
  end
12
12
  end
13
13
 
14
14
  namespace :admin do
15
- resources :polls, except: [:show] do
16
- get :results, on: :member
17
- end
18
-
15
+ resources :polls
19
16
  resources :poll_notifications, except: [:show]
20
17
  resources :poll_questions, except: [:show]
21
18
  end
@@ -8,6 +8,8 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
8
8
  t.datetime :end_at
9
9
 
10
10
  t.string :audience
11
+
12
+ t.string :audience_class_name
11
13
  t.text :audience_scope
12
14
 
13
15
  t.datetime :updated_at
@@ -15,7 +17,7 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
15
17
  end
16
18
 
17
19
  create_table :poll_notifications do |t|
18
- t.integer :poll_id
20
+ t.references :poll, polymorphic: false
19
21
 
20
22
  t.string :category
21
23
  t.integer :reminder
@@ -32,7 +34,7 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
32
34
  end
33
35
 
34
36
  create_table :poll_questions do |t|
35
- t.integer :poll_id
37
+ t.references :poll, polymorphic: false
36
38
 
37
39
  t.string :title
38
40
  t.string :category
@@ -45,7 +47,7 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
45
47
  end
46
48
 
47
49
  create_table :poll_question_options do |t|
48
- t.integer :poll_question_id
50
+ t.references :poll_question, polymorphic: false
49
51
 
50
52
  t.string :title
51
53
  t.integer :position
@@ -55,8 +57,8 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
55
57
  end
56
58
 
57
59
  create_table :ballots do |t|
58
- t.integer :poll_id
59
- t.integer :user_id
60
+ t.references :poll, polymorphic: false
61
+ t.references :user, polymorphic: true
60
62
 
61
63
  t.string :token
62
64
  t.text :wizard_steps
@@ -67,9 +69,9 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
67
69
  end
68
70
 
69
71
  create_table :ballot_responses do |t|
70
- t.integer :ballot_id
71
- t.integer :poll_id
72
- t.integer :poll_question_id
72
+ t.references :ballot, polymorphic: false
73
+ t.references :poll, polymorphic: false
74
+ t.references :poll_question, polymorphic: false
73
75
 
74
76
  t.date :date
75
77
  t.string :email
@@ -82,8 +84,8 @@ class CreateEffectivePolls < ActiveRecord::Migration[6.0]
82
84
  end
83
85
 
84
86
  create_table :ballot_response_options do |t|
85
- t.integer :ballot_response_id
86
- t.integer :poll_question_option_id
87
+ t.references :ballot_response, polymorphic: false
88
+ t.references :poll_question_option, polymorphic: false
87
89
 
88
90
  t.datetime :updated_at
89
91
  t.datetime :created_at
data/db/seeds.rb CHANGED
@@ -9,7 +9,8 @@ def build_effective_poll
9
9
  title: 'Effective Poll',
10
10
  start_at: (Time.zone.now + 1.day).beginning_of_day,
11
11
  end_at: (Time.zone.now + 1.day).end_of_day,
12
- audience: 'All Users'
12
+ audience: 'All Users',
13
+ audience_class_name: 'User'
13
14
  )
14
15
 
15
16
  build_poll_question(poll, Effective::PollQuestion::CATEGORIES)
@@ -7,5 +7,12 @@ module EffectivePolls
7
7
  eval File.read("#{config.root}/config/effective_polls.rb")
8
8
  end
9
9
 
10
+ # Include effective_polls_user concern and allow any ActiveRecord object to call it
11
+ initializer 'effective_polls.active_record' do |app|
12
+ app.config.to_prepare do
13
+ ActiveRecord::Base.extend(EffectivePollsUser::Base)
14
+ end
15
+ end
16
+
10
17
  end
11
18
  end
@@ -1,3 +1,3 @@
1
1
  module EffectivePolls
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -7,10 +7,8 @@ module EffectivePolls
7
7
 
8
8
  def self.config_keys
9
9
  [
10
- :polls_table_name, :poll_notifications_table_name, :poll_questions_table_name, :poll_question_options_table_name,
11
- :ballots_table_name, :ballot_responses_table_name, :ballot_response_options_table_name,
12
- :layout, :audience_user_scopes,
13
- :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates
10
+ :layout,
11
+ :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_froms, :mailer_admin, :mailer_subject, :use_effective_email_templates
14
12
  ]
15
13
  end
16
14
 
@@ -1,23 +1,34 @@
1
- # rake effective_polls:notify
1
+ # rake effective_polls:send_notifications
2
2
 
3
3
  namespace :effective_polls do
4
4
  desc 'Send email notifications for effective polls'
5
- task notify: :environment do
6
- poll_notifications = Effective::PollNotification.all.deep.notifiable
5
+ task send_notifications: :environment do
6
+ puts 'Sending notifications'
7
7
 
8
- poll_notifications.find_each do |notification|
9
- begin
10
- notified = notification.notify!
11
- puts "Sent #{notification.category} for #{notification.poll}" if notified
12
- rescue => e
13
- if defined?(ExceptionNotifier)
14
- ExceptionNotifier.notify_exception(e, data: { poll_notification_id: notification.id, poll_id: notification.poll_id })
15
- end
8
+ table = ActiveRecord::Base.connection.table_exists?(:poll_notifications)
9
+ blank_tenant = defined?(Tenant) && Tenant.current.blank?
16
10
 
17
- puts "Error with effective poll_notification #{notification.id}: #{e.errors.inspect}"
11
+ if table && !blank_tenant
12
+ poll_notifications = Effective::PollNotification.deep.notifiable
13
+
14
+ poll_notifications.find_each do |notification|
15
+ begin
16
+ notified = notification.notify!
17
+ puts "Sent #{notification.category} for #{notification.poll}" if notified
18
+ rescue StandardError => e
19
+ data = { poll_notification_id: notification.id, poll_id: notification.poll_id }
20
+ ExceptionNotifier.notify_exception(e, data: data) if defined?(ExceptionNotifier)
21
+ puts "Error with effective poll_notification #{notification.id}: #{e.errors.inspect}"
22
+ end
18
23
  end
19
24
  end
20
25
 
21
26
  puts 'All done'
22
27
  end
28
+
29
+ # Deprecated version
30
+ task notify: :environment do
31
+ Rake::Task['effective_polls:send_notifications'].invoke
32
+ end
33
+
23
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_polls
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-05 00:00:00.000000000 Z
11
+ date: 2023-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -227,9 +227,10 @@ files:
227
227
  - app/datatables/admin/effective_poll_questions_datatable.rb
228
228
  - app/datatables/admin/effective_poll_results_datatable.rb
229
229
  - app/datatables/admin/effective_polls_datatable.rb
230
- - app/datatables/effective_polls_datatable.rb
230
+ - app/datatables/effective_polls_available_polls_datatable.rb
231
231
  - app/helpers/effective_polls_helper.rb
232
232
  - app/mailers/effective/polls_mailer.rb
233
+ - app/models/concerns/effective_polls_user.rb
233
234
  - app/models/effective/ballot.rb
234
235
  - app/models/effective/ballot_response.rb
235
236
  - app/models/effective/ballot_response_option.rb
@@ -247,7 +248,7 @@ files:
247
248
  - app/views/admin/polls/_form.html.haml
248
249
  - app/views/admin/polls/_form_content.html.haml
249
250
  - app/views/admin/polls/_form_poll.html.haml
250
- - app/views/admin/polls/results.html.haml
251
+ - app/views/admin/polls/_poll.html.haml
251
252
  - app/views/effective/ballot_responses/_ballot_response.html.haml
252
253
  - app/views/effective/ballot_responses/_fields.html.haml
253
254
  - app/views/effective/ballot_responses/fields/_choose_one.html.haml
@@ -277,6 +278,8 @@ files:
277
278
  - app/views/effective/ballot_responses/responses/_short_answer.html.haml
278
279
  - app/views/effective/ballot_responses/responses/_upload_file.html.haml
279
280
  - app/views/effective/ballots/_ballot.html.haml
281
+ - app/views/effective/ballots/_content.html.haml
282
+ - app/views/effective/ballots/_layout.html.haml
280
283
  - app/views/effective/ballots/complete.html.haml
281
284
  - app/views/effective/ballots/start.html.haml
282
285
  - app/views/effective/ballots/submit.html.haml
@@ -297,12 +300,14 @@ files:
297
300
  - app/views/effective/poll_results/results/_select_up_to_5.html.haml
298
301
  - app/views/effective/poll_results/results/_short_answer.html.haml
299
302
  - app/views/effective/poll_results/results/_upload_file.html.haml
303
+ - app/views/effective/polls/_dashboard.html.haml
300
304
  - app/views/effective/polls_mailer/poll_before_poll_ends.liquid
301
305
  - app/views/effective/polls_mailer/poll_reminder.liquid
302
306
  - app/views/effective/polls_mailer/poll_upcoming_reminder.liquid
303
307
  - app/views/effective/polls_mailer/poll_when_poll_ends.liquid
304
308
  - app/views/effective/polls_mailer/poll_when_poll_starts.liquid
305
309
  - config/effective_polls.rb
310
+ - config/locales/effective_polls.yml
306
311
  - config/routes.rb
307
312
  - db/migrate/101_create_effective_polls.rb
308
313
  - db/seeds.rb
@@ -1,6 +0,0 @@
1
- %h1= @page_title
2
-
3
- = render 'effective/poll_results/results', poll: @poll
4
-
5
- %h2 Raw Results
6
- = render_datatable(@datatable)