effective_polls 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/admin/polls_controller.rb +1 -7
- data/app/controllers/effective/ballots_controller.rb +4 -1
- data/app/datatables/admin/effective_poll_notifications_datatable.rb +4 -1
- data/app/datatables/admin/effective_poll_results_datatable.rb +1 -4
- data/app/datatables/admin/effective_polls_datatable.rb +1 -0
- data/app/datatables/{effective_polls_datatable.rb → effective_polls_available_polls_datatable.rb} +6 -4
- data/app/helpers/effective_polls_helper.rb +17 -13
- data/app/mailers/effective/polls_mailer.rb +3 -1
- data/app/models/concerns/effective_polls_user.rb +67 -0
- data/app/models/effective/ballot.rb +11 -2
- data/app/models/effective/ballot_response.rb +1 -1
- data/app/models/effective/poll.rb +39 -26
- data/app/models/effective/poll_notification.rb +2 -2
- data/app/models/effective/poll_question.rb +1 -1
- data/app/models/effective/poll_question_option.rb +1 -1
- data/app/views/admin/poll_notifications/_form.html.haml +3 -5
- data/app/views/admin/poll_questions/_form.html.haml +12 -5
- data/app/views/admin/polls/_form.html.haml +10 -5
- data/app/views/admin/polls/_form_content.html.haml +16 -20
- data/app/views/admin/polls/_form_poll.html.haml +16 -7
- data/app/views/admin/polls/_poll.html.haml +5 -0
- data/app/views/effective/ballots/_content.html.haml +10 -0
- data/app/views/effective/ballots/_layout.html.haml +3 -0
- data/app/views/effective/ballots/complete.html.haml +13 -8
- data/app/views/effective/ballots/start.html.haml +29 -12
- data/app/views/effective/ballots/submit.html.haml +10 -13
- data/app/views/effective/ballots/vote.html.haml +10 -15
- data/app/views/effective/poll_results/_results.html.haml +2 -2
- data/app/views/effective/polls/_dashboard.html.haml +25 -0
- data/app/views/effective/polls_mailer/poll_before_poll_ends.liquid +0 -1
- data/app/views/effective/polls_mailer/poll_reminder.liquid +0 -1
- data/app/views/effective/polls_mailer/poll_upcoming_reminder.liquid +0 -1
- data/app/views/effective/polls_mailer/poll_when_poll_ends.liquid +0 -1
- data/app/views/effective/polls_mailer/poll_when_poll_starts.liquid +0 -1
- data/config/effective_polls.rb +2 -11
- data/config/locales/effective_polls.yml +14 -0
- data/config/routes.rb +2 -5
- data/db/migrate/101_create_effective_polls.rb +12 -10
- data/db/seeds.rb +2 -1
- data/lib/effective_polls/engine.rb +7 -0
- data/lib/effective_polls/version.rb +1 -1
- data/lib/effective_polls.rb +2 -4
- data/lib/tasks/effective_polls_tasks.rake +23 -12
- metadata +9 -4
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 637320f25a72489ada773806629e70590bb5c8435e871a6de40497e2eb6300ed
|
4
|
+
data.tar.gz: e797d1afdad6be66099b291ec7a809cbb65ef32d7963ca04f03d3ac3d91fe2a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
|
@@ -41,10 +41,7 @@ class Admin::EffectivePollResultsDatatable < Effective::Datatable
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def poll
|
44
|
-
@poll ||=
|
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
|
data/app/datatables/{effective_polls_datatable.rb → effective_polls_available_polls_datatable.rb}
RENAMED
@@ -1,13 +1,14 @@
|
|
1
|
+
# Dashboard available polls
|
1
2
|
# Displays available polls that the current_user may complete
|
2
3
|
|
3
|
-
class
|
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
|
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
|
-
|
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
|
-
|
6
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
19
|
-
|
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
|
-
|
60
|
+
model_name.human
|
52
61
|
end
|
53
62
|
|
54
63
|
# Find or build
|
@@ -1,10 +1,6 @@
|
|
1
1
|
module Effective
|
2
2
|
class Poll < ActiveRecord::Base
|
3
|
-
|
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
|
-
|
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
|
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
|
40
|
-
|
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 ||
|
75
|
+
title.presence || model_name.human
|
79
76
|
end
|
80
77
|
|
81
78
|
def available_for?(user)
|
82
|
-
raise('expected
|
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
|
-
|
95
|
+
klass.try(:unarchived) || klass.all
|
90
96
|
when 'Individual Users'
|
91
|
-
|
97
|
+
(klass.try(:unarchived) || klass.all).where(id: audience_scope)
|
92
98
|
when 'Selected Users'
|
93
|
-
collection =
|
94
|
-
|
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
|
-
'
|
84
|
+
[category.presence, subject.presence].compact.join(' - ') || model_name.human
|
85
85
|
end
|
86
86
|
|
87
87
|
def email_template
|
@@ -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.
|
5
|
+
= f.select :poll_id, Effective::Poll.all
|
6
6
|
|
7
7
|
= f.text_field :title, label: 'Question Title'
|
8
|
-
|
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
|
17
|
-
%p Display
|
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(
|
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, '
|
16
|
+
= pluralize(poll.users.count, 'user')
|
17
17
|
in the audience.
|
18
18
|
|
19
|
-
|
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?(:
|
27
|
+
- if poll.respond_to?(:logs_datatable)
|
23
28
|
= tab 'Logs' do
|
24
|
-
= render_datatable(poll.
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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
|
-
.
|
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
|
-
.
|
18
|
-
.
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
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
|
-
|
23
|
-
|
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,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
|
@@ -1,11 +1,16 @@
|
|
1
|
-
=
|
2
|
-
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/ballots/content', resource: resource
|
3
3
|
|
4
|
-
-
|
5
|
-
.mb-2= resource.poll.all_steps_content
|
4
|
+
- raise('expected a completed? poll') unless resource.completed?
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
.alert.alert-warning.mb-4
|
7
|
+
Successfully completed on #{resource.completed_at.strftime('%F')}.
|
9
8
|
|
10
|
-
.
|
11
|
-
|
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
|
-
=
|
2
|
-
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/ballots/content', resource: resource
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
- # Signed out
|
5
|
+
- if resource.user.blank?
|
6
|
+
= card do
|
7
|
+
%p Welcome!
|
7
8
|
|
8
|
-
|
9
|
-
.mb-2= resource.poll.all_steps_content
|
9
|
+
%p You are about to register for #{resource.poll}.
|
10
10
|
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
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
|
-
=
|
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
|
-
=
|
2
|
-
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/ballots/content', resource: resource
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
= card do
|
5
|
+
%p= resource.poll
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
8
|
+
= f.hidden_field :current_step
|
9
9
|
|
10
|
-
|
11
|
-
= f.hidden_field :current_step
|
10
|
+
= render(resource)
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
=
|
2
|
-
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/ballots/content', resource: resource
|
3
3
|
|
4
|
-
|
5
|
-
|
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
|
-
|
8
|
-
|
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
|
-
|
11
|
-
|
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
|
-
|
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, '
|
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
|
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.
|
data/config/effective_polls.rb
CHANGED
@@ -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:
|
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
|
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.
|
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.
|
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.
|
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.
|
59
|
-
t.
|
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.
|
71
|
-
t.
|
72
|
-
t.
|
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.
|
86
|
-
t.
|
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
|
data/lib/effective_polls.rb
CHANGED
@@ -7,10 +7,8 @@ module EffectivePolls
|
|
7
7
|
|
8
8
|
def self.config_keys
|
9
9
|
[
|
10
|
-
:
|
11
|
-
:
|
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:
|
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
|
6
|
-
|
5
|
+
task send_notifications: :environment do
|
6
|
+
puts 'Sending notifications'
|
7
7
|
|
8
|
-
|
9
|
-
|
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
|
-
|
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.
|
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-
|
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/
|
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/
|
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
|