effective_polls 0.0.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +51 -20
- data/app/controllers/admin/poll_notifications_controller.rb +1 -1
- data/app/controllers/admin/poll_questions_controller.rb +1 -1
- data/app/controllers/admin/polls_controller.rb +1 -1
- data/app/controllers/effective/ballots_controller.rb +1 -1
- data/app/datatables/admin/effective_polls_datatable.rb +2 -2
- data/app/mailers/effective/polls_mailer.rb +58 -10
- data/app/models/effective/ballot_response.rb +6 -6
- data/app/models/effective/poll.rb +9 -18
- data/app/models/effective/poll_notification.rb +18 -18
- data/app/models/effective/poll_question.rb +11 -10
- data/app/views/admin/poll_notifications/_form.html.haml +24 -37
- data/app/views/admin/poll_notifications/_form_poll_reminder.html.haml +8 -0
- data/app/views/admin/poll_notifications/_form_poll_upcoming_reminder.html.haml +8 -0
- data/app/views/admin/poll_notifications/_form_poll_when_poll_ends.html.haml +3 -0
- data/app/views/admin/poll_notifications/_form_poll_when_poll_starts.html.haml +3 -0
- data/app/views/admin/poll_questions/_form.html.haml +15 -15
- data/app/views/admin/polls/_form.html.haml +5 -1
- data/app/views/admin/polls/_form_poll.html.haml +2 -2
- data/app/views/effective/ballot_responses/fields/_date.html.haml +2 -1
- data/app/views/effective/ballot_responses/fields/_email.html.haml +2 -1
- data/app/views/effective/ballot_responses/fields/_number.html.haml +2 -1
- data/app/views/effective/ballot_responses/fields/{_select_upto_1.html.haml → _select_up_to_1.html.haml} +0 -0
- data/app/views/effective/ballot_responses/fields/{_select_upto_2.html.haml → _select_up_to_2.html.haml} +0 -0
- data/app/views/effective/ballot_responses/fields/{_select_upto_3.html.haml → _select_up_to_3.html.haml} +0 -0
- data/app/views/effective/ballot_responses/fields/{_select_upto_4.html.haml → _select_up_to_4.html.haml} +0 -0
- data/app/views/effective/ballot_responses/fields/{_select_upto_5.html.haml → _select_up_to_5.html.haml} +0 -0
- data/app/views/effective/ballot_responses/responses/{_select_upto_1.html.haml → _select_up_to_1.html.haml} +0 -0
- data/app/views/effective/ballot_responses/responses/{_select_upto_2.html.haml → _select_up_to_2.html.haml} +0 -0
- data/app/views/effective/ballot_responses/responses/{_select_upto_3.html.haml → _select_up_to_3.html.haml} +0 -0
- data/app/views/effective/ballot_responses/responses/{_select_upto_4.html.haml → _select_up_to_4.html.haml} +0 -0
- data/app/views/effective/ballot_responses/responses/{_select_upto_5.html.haml → _select_up_to_5.html.haml} +0 -0
- data/app/views/effective/ballots/_ballot.html.haml +2 -2
- data/app/views/effective/ballots/start.html.haml +1 -1
- data/app/views/effective/ballots/submit.html.haml +1 -1
- data/app/views/effective/ballots/vote.html.haml +1 -1
- data/app/views/effective/poll_results/_results.html.haml +1 -1
- data/app/views/effective/poll_results/results/{_select_upto_1.html.haml → _select_up_to_1.html.haml} +0 -0
- data/app/views/effective/poll_results/results/{_select_upto_2.html.haml → _select_up_to_2.html.haml} +0 -0
- data/app/views/effective/poll_results/results/{_select_upto_3.html.haml → _select_up_to_3.html.haml} +0 -0
- data/app/views/effective/poll_results/results/{_select_upto_4.html.haml → _select_up_to_4.html.haml} +0 -0
- data/app/views/effective/poll_results/results/{_select_upto_5.html.haml → _select_up_to_5.html.haml} +0 -0
- data/app/views/effective/polls_mailer/poll_reminder.liquid +13 -0
- data/app/views/effective/polls_mailer/poll_upcoming_reminder.liquid +11 -0
- data/app/views/effective/polls_mailer/poll_when_poll_ends.liquid +9 -0
- data/app/views/effective/polls_mailer/poll_when_poll_starts.liquid +13 -0
- data/config/effective_polls.rb +6 -1
- data/db/migrate/01_create_effective_polls.rb.erb +1 -0
- data/lib/effective_polls.rb +8 -3
- data/lib/effective_polls/version.rb +1 -1
- data/lib/generators/effective_polls/install_generator.rb +1 -1
- data/lib/generators/templates/effective_polls_mailer_preview.rb +17 -8
- data/lib/tasks/effective_polls_tasks.rake +5 -6
- metadata +25 -90
- data/app/views/admin/polls/_poll.html.haml +0 -2
- data/app/views/effective/polls/_form.html.haml +0 -10
- data/app/views/effective/polls/_poll.html.haml +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aebcfa6f3efd89aa11a576d324f53b5d1438b94c8f71d2253c307898f600abef
|
4
|
+
data.tar.gz: c93f89535c8d5938d1025cf106f0a914b395e8b45c6992d48a02b9dd4a4465af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 787542d8c6ef91a83f68eded3aaf00455b36342e5e54a0572869d3d31588d307d2e2c0c96520560b77487227925b41927404b8622bf891bb422c89ca187c6ed7
|
7
|
+
data.tar.gz: 48a308bcaa45d2a478f918c5fa714aa870581a6ec572a5f08489550ce30740272ac1386668e0c3500b4567e789bc987790f46504a666700cc668ae7053e65059
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -2,21 +2,24 @@
|
|
2
2
|
|
3
3
|
Online polls and user voting.
|
4
4
|
|
5
|
-
An admin creates polls with one or more poll_questions. The poll can be assigned to users
|
5
|
+
An admin creates polls with one or more poll_questions. The poll can be assigned to all users, individual users or selected users (a scope) and those users complete a 4-step wizard to submit a poll.
|
6
6
|
|
7
|
-
|
7
|
+
All results are anonymized such that the user cannot be identified from the results.
|
8
8
|
|
9
|
-
|
9
|
+
Works with action_text for content bodies, and active_storage for file uploads.
|
10
10
|
|
11
11
|
## Getting Started
|
12
12
|
|
13
|
+
This requires Rails 6+ and Twitter Bootstrap 4 and just works with Devise.
|
14
|
+
|
13
15
|
Please first install the [effective_datatables](https://github.com/code-and-effect/effective_datatables) gem.
|
14
16
|
|
15
|
-
Please download and install [Twitter Bootstrap4](http://getbootstrap.com)
|
17
|
+
Please download and install the [Twitter Bootstrap4](http://getbootstrap.com)
|
16
18
|
|
17
19
|
Add to your Gemfile:
|
18
20
|
|
19
21
|
```ruby
|
22
|
+
gem 'haml-rails' # or try using gem 'hamlit-rails'
|
20
23
|
gem 'effective_polls'
|
21
24
|
```
|
22
25
|
|
@@ -34,7 +37,7 @@ rails generate effective_polls:install
|
|
34
37
|
|
35
38
|
The generator will install an initializer which describes all configuration options and creates a database migration.
|
36
39
|
|
37
|
-
If you want to tweak the table
|
40
|
+
If you want to tweak the table names, manually adjust both the configuration file and the migration now.
|
38
41
|
|
39
42
|
Then migrate the database:
|
40
43
|
|
@@ -42,9 +45,50 @@ Then migrate the database:
|
|
42
45
|
rake db:migrate
|
43
46
|
```
|
44
47
|
|
45
|
-
|
48
|
+
Render the "available polls for current_user" datatable on your user dashboard:
|
49
|
+
|
50
|
+
```haml
|
51
|
+
%h2 Polls
|
52
|
+
%p You may submit a ballot for the following polls.
|
53
|
+
= render_datatable(EffectivePollsDatatable.new, simple: true)
|
54
|
+
```
|
55
|
+
|
56
|
+
Add a link to the admin menu:
|
57
|
+
|
58
|
+
```haml
|
59
|
+
- if can? :admin, :effective_polls
|
60
|
+
= link_to 'Polls', effective_polls.admin_polls_path
|
61
|
+
```
|
62
|
+
|
63
|
+
Set up your permissions:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# Regular signed up user. Guest users not supported.
|
67
|
+
if user.persisted?
|
68
|
+
can [:show, :update], Effective::Ballot, user_id: user.id
|
69
|
+
can :show, Effective::Poll
|
70
|
+
can :index, EffectivePollsDatatable
|
71
|
+
end
|
72
|
+
|
73
|
+
if user.admin?
|
74
|
+
can :admin, :effective_polls
|
46
75
|
|
47
|
-
|
76
|
+
can :manage, Effective::Poll
|
77
|
+
can :manage, Effective::PollNotification
|
78
|
+
can :manage, Effective::PollQuestion
|
79
|
+
can :index, Admin::EffectivePollResultsDatatable
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
And, if you want to use poll notifications, schedule the rake task to run every 10 minutes, or faster:
|
84
|
+
|
85
|
+
```rake
|
86
|
+
rake effective_polls:notify
|
87
|
+
```
|
88
|
+
|
89
|
+
## Usage
|
90
|
+
|
91
|
+
You can render the results with `render('effective/poll_results/results', poll: poll)`.
|
48
92
|
|
49
93
|
## Authorization
|
50
94
|
|
@@ -97,19 +141,6 @@ rescue_from Effective::AccessDenied do |exception|
|
|
97
141
|
end
|
98
142
|
```
|
99
143
|
|
100
|
-
### Permissions
|
101
|
-
|
102
|
-
The permissions you actually want to define are as follows (using CanCan):
|
103
|
-
|
104
|
-
```ruby
|
105
|
-
can [:index, :show], Effective::Poll
|
106
|
-
|
107
|
-
if user.admin?
|
108
|
-
can :manage, Effective::Poll
|
109
|
-
can :admin, :effective_polls
|
110
|
-
end
|
111
|
-
```
|
112
|
-
|
113
144
|
## License
|
114
145
|
|
115
146
|
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Admin
|
2
2
|
class PollNotificationsController < ApplicationController
|
3
|
-
layout
|
3
|
+
layout EffectivePolls.layout[:admin]
|
4
4
|
|
5
5
|
before_action(:authenticate_user!) if defined?(Devise)
|
6
6
|
before_action { EffectivePolls.authorize!(self, :admin, :effective_polls) }
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Admin
|
2
2
|
class PollQuestionsController < ApplicationController
|
3
|
-
layout
|
3
|
+
layout EffectivePolls.layout[:admin]
|
4
4
|
|
5
5
|
before_action(:authenticate_user!) if defined?(Devise)
|
6
6
|
before_action { EffectivePolls.authorize!(self, :admin, :effective_polls) }
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Admin
|
2
2
|
class PollsController < ApplicationController
|
3
|
-
layout
|
3
|
+
layout EffectivePolls.layout[:admin]
|
4
4
|
|
5
5
|
before_action(:authenticate_user!) if defined?(Devise)
|
6
6
|
before_action { EffectivePolls.authorize!(self, :admin, :effective_polls) }
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Effective
|
2
2
|
class BallotsController < ApplicationController
|
3
|
-
layout
|
3
|
+
layout EffectivePolls.layout[:polls]
|
4
4
|
|
5
5
|
before_action(:authenticate_user!) if defined?(Devise)
|
6
6
|
include Effective::WizardController
|
@@ -1,15 +1,15 @@
|
|
1
1
|
class Admin::EffectivePollsDatatable < Effective::Datatable
|
2
2
|
filters do
|
3
|
+
scope :all
|
3
4
|
scope :upcoming
|
4
5
|
scope :available
|
5
6
|
scope :completed
|
6
|
-
scope :all
|
7
7
|
end
|
8
8
|
|
9
9
|
datatable do
|
10
10
|
order :start_at, :desc
|
11
11
|
|
12
|
-
col :
|
12
|
+
col :token, visible: false
|
13
13
|
col :created_at, visible: false
|
14
14
|
col :updated_at, visible: false
|
15
15
|
|
@@ -1,22 +1,70 @@
|
|
1
1
|
module Effective
|
2
|
-
class PollsMailer <
|
3
|
-
default from: EffectivePolls.mailer[:default_from]
|
2
|
+
class PollsMailer < EffectivePolls.mailer_class
|
4
3
|
layout EffectivePolls.mailer[:layout].presence || 'effective_polls_mailer_layout'
|
5
4
|
|
6
|
-
def poll_upcoming_reminder(poll_notification,
|
7
|
-
|
5
|
+
def poll_upcoming_reminder(poll_notification, user)
|
6
|
+
@assigns = effective_email_templates_assigns(poll_notification, user)
|
7
|
+
|
8
|
+
mail(
|
9
|
+
to: user.email,
|
10
|
+
from: poll_notification.from,
|
11
|
+
body: poll_notification.body,
|
12
|
+
subject: poll_notification.subject
|
13
|
+
)
|
8
14
|
end
|
9
15
|
|
10
|
-
def
|
11
|
-
|
16
|
+
def poll_when_poll_starts(poll_notification, user)
|
17
|
+
@assigns = effective_email_templates_assigns(poll_notification, user)
|
18
|
+
|
19
|
+
mail(
|
20
|
+
to: user.email,
|
21
|
+
from: poll_notification.from,
|
22
|
+
body: poll_notification.body,
|
23
|
+
subject: poll_notification.subject
|
24
|
+
)
|
12
25
|
end
|
13
26
|
|
14
|
-
def poll_reminder(poll_notification,
|
15
|
-
|
27
|
+
def poll_reminder(poll_notification, user)
|
28
|
+
@assigns = effective_email_templates_assigns(poll_notification, user)
|
29
|
+
|
30
|
+
mail(
|
31
|
+
to: user.email,
|
32
|
+
from: poll_notification.from,
|
33
|
+
body: poll_notification.body,
|
34
|
+
subject: poll_notification.subject
|
35
|
+
)
|
16
36
|
end
|
17
37
|
|
18
|
-
def
|
19
|
-
|
38
|
+
def poll_when_poll_ends(poll_notification, user)
|
39
|
+
@assigns = effective_email_templates_assigns(poll_notification, user)
|
40
|
+
|
41
|
+
mail(
|
42
|
+
to: user.email,
|
43
|
+
from: poll_notification.from,
|
44
|
+
body: poll_notification.body,
|
45
|
+
subject: poll_notification.subject
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Only relevant if the effective_email_templates gem is present
|
52
|
+
def effective_email_templates_assigns(poll_notification, user)
|
53
|
+
raise('expected an Effective::PollNotification') unless poll_notification.kind_of?(Effective::PollNotification)
|
54
|
+
raise('expected a User') unless user.kind_of?(User)
|
55
|
+
|
56
|
+
poll = poll_notification.poll
|
57
|
+
raise('expected poll to be persisted') unless poll&.persisted?
|
58
|
+
|
59
|
+
{
|
60
|
+
available_date: poll.available_date,
|
61
|
+
title: poll.title,
|
62
|
+
url: effective_polls.new_poll_ballot_url(poll),
|
63
|
+
user: {
|
64
|
+
name: user.to_s,
|
65
|
+
email: user.email
|
66
|
+
}
|
67
|
+
}
|
20
68
|
end
|
21
69
|
|
22
70
|
end
|
@@ -48,19 +48,19 @@ module Effective
|
|
48
48
|
validates :poll_question_option_ids, if: -> { poll_question&.choose_one? },
|
49
49
|
length: { maximum: 1, message: 'please choose 1 option only' }
|
50
50
|
|
51
|
-
validates :poll_question_option_ids, if: -> { poll_question&.
|
51
|
+
validates :poll_question_option_ids, if: -> { poll_question&.select_up_to_1? },
|
52
52
|
length: { maximum: 1, message: 'please select 1 option or fewer' }
|
53
53
|
|
54
|
-
validates :poll_question_option_ids, if: -> { poll_question&.
|
54
|
+
validates :poll_question_option_ids, if: -> { poll_question&.select_up_to_2? },
|
55
55
|
length: { maximum: 2, message: 'please select 2 options or fewer' }
|
56
56
|
|
57
|
-
validates :poll_question_option_ids, if: -> { poll_question&.
|
57
|
+
validates :poll_question_option_ids, if: -> { poll_question&.select_up_to_3? },
|
58
58
|
length: { maximum: 3, message: 'please select 3 options or fewer' }
|
59
59
|
|
60
|
-
validates :poll_question_option_ids, if: -> { poll_question&.
|
60
|
+
validates :poll_question_option_ids, if: -> { poll_question&.select_up_to_4? },
|
61
61
|
length: { maximum: 4, message: 'please select 4 options or fewer' }
|
62
62
|
|
63
|
-
validates :poll_question_option_ids, if: -> { poll_question&.
|
63
|
+
validates :poll_question_option_ids, if: -> { poll_question&.select_up_to_5? },
|
64
64
|
length: { maximum: 5, message: 'please select 5 options or fewer' }
|
65
65
|
|
66
66
|
def to_s
|
@@ -78,7 +78,7 @@ module Effective
|
|
78
78
|
return upload_file if poll_question.upload_file?
|
79
79
|
|
80
80
|
return poll_question_options.first if poll_question.choose_one?
|
81
|
-
return poll_question_options.first if poll_question.
|
81
|
+
return poll_question_options.first if poll_question.select_up_to_1?
|
82
82
|
return poll_question_options if poll_question.poll_question_option?
|
83
83
|
|
84
84
|
raise('unknown response for unexpected poll question category')
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Effective
|
2
2
|
class Poll < ActiveRecord::Base
|
3
|
-
attr_accessor :skip_started_validation
|
4
|
-
|
5
3
|
has_rich_text :all_steps_content
|
6
4
|
has_rich_text :start_content
|
7
5
|
has_rich_text :vote_content
|
@@ -23,6 +21,10 @@ module Effective
|
|
23
21
|
|
24
22
|
acts_as_tokened
|
25
23
|
|
24
|
+
if respond_to?(:log_changes)
|
25
|
+
log_changes(except: [:ballots, :ballot_responses, :completed_ballots, :completed_ballot_responses])
|
26
|
+
end
|
27
|
+
|
26
28
|
AUDIENCES = ['All Users', 'Individual Users', 'Selected Users']
|
27
29
|
|
28
30
|
effective_resource do
|
@@ -57,7 +59,6 @@ module Effective
|
|
57
59
|
}
|
58
60
|
|
59
61
|
scope :sorted, -> { order(:start_at) }
|
60
|
-
scope :editable, -> { upcoming }
|
61
62
|
|
62
63
|
scope :upcoming, -> { where('start_at > ?', Time.zone.now) }
|
63
64
|
scope :available, -> { where('start_at <= ? AND (end_at > ? OR end_at IS NULL)', Time.zone.now, Time.zone.now) }
|
@@ -69,14 +70,6 @@ module Effective
|
|
69
70
|
validates :audience, inclusion: { in: AUDIENCES }
|
70
71
|
validates :audience_scope, presence: true, unless: -> { audience == 'All Users' }
|
71
72
|
|
72
|
-
validate(if: -> { started? }, unless: -> { skip_started_validation }) do
|
73
|
-
self.errors.add(:base, 'has already started. a poll cannot be changed after it has started.')
|
74
|
-
end
|
75
|
-
|
76
|
-
validate(if: -> { start_at.present? && !started? }, unless: -> { skip_started_validation }) do
|
77
|
-
self.errors.add(:start_at, 'must be a future date') if start_at < Time.zone.now
|
78
|
-
end
|
79
|
-
|
80
73
|
validate(if: -> { start_at.present? && end_at.present? }) do
|
81
74
|
self.errors.add(:end_at, 'must be after the start date') unless end_at > start_at
|
82
75
|
end
|
@@ -90,8 +83,8 @@ module Effective
|
|
90
83
|
available? && users.include?(user)
|
91
84
|
end
|
92
85
|
|
93
|
-
def users
|
94
|
-
case audience
|
86
|
+
def users(except_completed: false)
|
87
|
+
users = case audience
|
95
88
|
when 'All Users'
|
96
89
|
User.all
|
97
90
|
when 'Individual Users'
|
@@ -103,13 +96,11 @@ module Effective
|
|
103
96
|
else
|
104
97
|
raise('unexpected audience')
|
105
98
|
end
|
106
|
-
end
|
107
99
|
|
108
|
-
|
109
|
-
|
110
|
-
users.where.not(id: completed_ballots.select('user_id as id')).pluck(:email)
|
100
|
+
if except_completed
|
101
|
+
users.where.not(id: completed_ballots.select('user_id as id'))
|
111
102
|
else
|
112
|
-
users
|
103
|
+
users
|
113
104
|
end
|
114
105
|
end
|
115
106
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Effective
|
2
2
|
class PollNotification < ActiveRecord::Base
|
3
3
|
belongs_to :poll
|
4
|
+
log_changes(to: :poll) if respond_to?(:log_changes)
|
4
5
|
|
5
|
-
BATCHSIZE = (Rails.env.test? ? 3 : 250)
|
6
6
|
CATEGORIES = ['Upcoming reminder', 'When poll starts', 'Reminder', 'When poll ends']
|
7
|
+
EMAIL_TEMPLATE_VARIABLES = ['available_date', 'title', 'url', 'user.name', 'user.email']
|
7
8
|
|
8
9
|
UPCOMING_REMINDERS = {
|
9
10
|
'1 hour before' => 1.hours.to_i,
|
@@ -44,6 +45,7 @@ module Effective
|
|
44
45
|
reminder :integer # Number of seconds before poll.start_at
|
45
46
|
|
46
47
|
# Email
|
48
|
+
from :string
|
47
49
|
subject :string
|
48
50
|
body :text
|
49
51
|
|
@@ -65,9 +67,16 @@ module Effective
|
|
65
67
|
|
66
68
|
validates :poll, presence: true
|
67
69
|
validates :category, presence: true, inclusion: { in: CATEGORIES }
|
70
|
+
|
71
|
+
validates :from, presence: true
|
68
72
|
validates :subject, presence: true
|
69
73
|
validates :body, presence: true
|
70
74
|
|
75
|
+
if EffectivePolls.use_effective_email_templates
|
76
|
+
validates :body, liquid: true
|
77
|
+
validates :subject, liquid: true
|
78
|
+
end
|
79
|
+
|
71
80
|
validates :reminder, if: -> { reminder? || upcoming_reminder? },
|
72
81
|
presence: true, uniqueness: { scope: [:poll_id, :category], message: 'already exists' }
|
73
82
|
|
@@ -75,6 +84,10 @@ module Effective
|
|
75
84
|
'poll notification'
|
76
85
|
end
|
77
86
|
|
87
|
+
def email_template
|
88
|
+
'poll_' + category.to_s.parameterize.underscore
|
89
|
+
end
|
90
|
+
|
78
91
|
def upcoming_reminder?
|
79
92
|
category == 'Upcoming reminder'
|
80
93
|
end
|
@@ -115,26 +128,13 @@ module Effective
|
|
115
128
|
def notify!
|
116
129
|
return false unless notify_now?
|
117
130
|
|
118
|
-
# We send to all
|
119
|
-
|
131
|
+
# We send to all users, except for the 'Reminder' that exclude completed users
|
132
|
+
users = poll.users(except_completed: (category == 'Reminder'))
|
120
133
|
|
121
134
|
update_column(:started_at, Time.zone.now)
|
122
135
|
|
123
|
-
|
124
|
-
|
125
|
-
when 'When poll starts'
|
126
|
-
Effective::PollsMailer.poll_start(self, emails)
|
127
|
-
when 'When poll ends'
|
128
|
-
Effective::PollsMailer.poll_end(self, emails)
|
129
|
-
when 'Upcoming reminder'
|
130
|
-
Effective::PollsMailer.poll_upcoming_reminder(self, emails)
|
131
|
-
when 'Reminder'
|
132
|
-
Effective::PollsMailer.poll_reminder(self, emails)
|
133
|
-
else
|
134
|
-
raise('unexpected category')
|
135
|
-
end
|
136
|
-
|
137
|
-
mail.deliver_now
|
136
|
+
users.find_each do |user|
|
137
|
+
Effective::PollsMailer.public_send(email_template, self, user).deliver_now
|
138
138
|
end
|
139
139
|
|
140
140
|
update_column(:completed_at, Time.zone.now)
|
@@ -6,15 +6,16 @@ module Effective
|
|
6
6
|
accepts_nested_attributes_for :poll_question_options, reject_if: :all_blank, allow_destroy: true
|
7
7
|
|
8
8
|
has_rich_text :body
|
9
|
+
log_changes(to: :poll) if respond_to?(:log_changes)
|
9
10
|
|
10
11
|
CATEGORIES = [
|
11
12
|
'Choose one', # Radios
|
12
13
|
'Select all that apply', # Checks
|
13
|
-
'Select
|
14
|
-
'Select
|
15
|
-
'Select
|
16
|
-
'Select
|
17
|
-
'Select
|
14
|
+
'Select up to 1',
|
15
|
+
'Select up to 2',
|
16
|
+
'Select up to 3',
|
17
|
+
'Select up to 4',
|
18
|
+
'Select up to 5',
|
18
19
|
'Date', # Date Field
|
19
20
|
'Email', # Email Field
|
20
21
|
'Number', # Numeric Field
|
@@ -26,11 +27,11 @@ module Effective
|
|
26
27
|
WITH_OPTIONS_CATEGORIES = [
|
27
28
|
'Choose one', # Radios
|
28
29
|
'Select all that apply', # Checks
|
29
|
-
'Select
|
30
|
-
'Select
|
31
|
-
'Select
|
32
|
-
'Select
|
33
|
-
'Select
|
30
|
+
'Select up to 1',
|
31
|
+
'Select up to 2',
|
32
|
+
'Select up to 3',
|
33
|
+
'Select up to 4',
|
34
|
+
'Select up to 5'
|
34
35
|
]
|
35
36
|
|
36
37
|
effective_resource do
|
@@ -2,54 +2,41 @@
|
|
2
2
|
- if inline_datatable?
|
3
3
|
= f.hidden_field :poll_id
|
4
4
|
- else
|
5
|
-
= f.select :poll_id, Effective::Poll.sorted.
|
5
|
+
= f.select :poll_id, Effective::Poll.sorted.all
|
6
6
|
|
7
7
|
= f.select :category, Effective::PollNotification::CATEGORIES,
|
8
8
|
label: 'Send an email notification'
|
9
9
|
|
10
|
-
|
10
|
+
- # Render email templates
|
11
|
+
- Effective::PollNotification::CATEGORIES.each do |category|
|
12
|
+
- template = 'poll_' + category.parameterize.underscore
|
11
13
|
|
12
|
-
= f.
|
13
|
-
|
14
|
+
= f.show_if :category, category do
|
15
|
+
= render "/admin/poll_notifications/form_#{template}", f: f
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Use upcoming reminders to advertise, prepare, or communicate to your audience before the poll begins.
|
17
|
+
- if f.object.category == category
|
18
|
+
= f.email_field :from
|
19
|
+
= f.text_field :subject
|
20
|
+
= f.text_area :body, rows: 10
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
- elsif EffectivePolls.use_effective_email_templates == false
|
23
|
+
= f.email_field :from, value: EffectivePolls.mailer[:default_from]
|
24
|
+
= f.text_field :subject, value: ''
|
25
|
+
= f.text_area :body, rows: 10, value: ''
|
25
26
|
|
26
|
-
|
27
|
+
- else
|
28
|
+
- email_template = Effective::EmailTemplate.where(template_name: template).first!
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
+
= f.email_field :from, value: email_template.from
|
31
|
+
= f.text_field :subject, value: email_template.subject
|
32
|
+
= f.text_area :body, rows: 10, value: email_template.body
|
30
33
|
|
31
|
-
|
32
|
-
%strong Reminders
|
33
|
-
are sent to users in the audience who have not yet completed their ballot.
|
34
|
-
%br
|
35
|
-
Use reminders to boost your audience participation and remind people to vote.
|
34
|
+
%p The available variables are:
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
notifications will be sent within 10 minutes of the poll end time.
|
36
|
+
%ul
|
37
|
+
- Effective::PollNotification::EMAIL_TEMPLATE_VARIABLES.each do |variable|
|
38
|
+
%li {{ #{variable} }}
|
41
39
|
|
42
|
-
|
43
|
-
= f.text_area :body, label: 'Email Body'
|
44
|
-
|
45
|
-
.alert.alert-warning
|
46
|
-
Email content must not contain any personal details.
|
47
|
-
%br
|
48
|
-
This content will be sent in a mass email with hundreds of bcc'd recipients.
|
49
|
-
|
50
|
-
- if poll_notification.poll.present?
|
51
|
-
%br
|
52
|
-
The url for this poll will be:
|
53
|
-
= effective_polls.poll_url(poll_notification.poll)
|
40
|
+
%small.text-muted Only a developer can add additional variables
|
54
41
|
|
55
42
|
= effective_submit(f)
|
@@ -0,0 +1,8 @@
|
|
1
|
+
= f.select :reminder, Effective::PollNotification::REMINDERS, label: false,
|
2
|
+
hint: "after the poll starts on #{f.object.poll&.start_at&.strftime('%F')}."
|
3
|
+
|
4
|
+
.alert.alert-warning
|
5
|
+
%strong Reminders
|
6
|
+
are sent to users in the audience who have not yet completed their ballot.
|
7
|
+
%br
|
8
|
+
Use reminders to boost your audience participation and remind people to vote.
|
@@ -0,0 +1,8 @@
|
|
1
|
+
= f.select :reminder, Effective::PollNotification::UPCOMING_REMINDERS, label: false,
|
2
|
+
hint: "before the poll starts on #{f.object.poll&.start_at&.strftime('%F')}."
|
3
|
+
|
4
|
+
.alert.alert-warning
|
5
|
+
%strong Upcoming Reminders
|
6
|
+
are sent to the entire audience before the poll starts.
|
7
|
+
%br
|
8
|
+
Use upcoming reminders to advertise, prepare, or communicate to your audience before the poll begins.
|
@@ -22,35 +22,35 @@
|
|
22
22
|
%h5 Select all that apply
|
23
23
|
%p Display checkboxes to select all options that apply
|
24
24
|
|
25
|
-
= f.show_if :category, 'Select
|
25
|
+
= f.show_if :category, 'Select up to 1' do
|
26
26
|
.card
|
27
27
|
.card-body
|
28
|
-
%h5 Select
|
29
|
-
%p Display checkboxes to select
|
28
|
+
%h5 Select up to 1 (one)
|
29
|
+
%p Display checkboxes to select up to 1 option
|
30
30
|
|
31
|
-
= f.show_if :category, 'Select
|
31
|
+
= f.show_if :category, 'Select up to 2' do
|
32
32
|
.card
|
33
33
|
.card-body
|
34
|
-
%h5 Select
|
35
|
-
%p Display checkboxes to select
|
34
|
+
%h5 Select up to 2 (two)
|
35
|
+
%p Display checkboxes to select up to 2 options
|
36
36
|
|
37
|
-
= f.show_if :category, 'Select
|
37
|
+
= f.show_if :category, 'Select up to 3' do
|
38
38
|
.card
|
39
39
|
.card-body
|
40
|
-
%h5 Select
|
41
|
-
%p Display checkboxes to select
|
40
|
+
%h5 Select up to 3 (three)
|
41
|
+
%p Display checkboxes to select up to 3 options
|
42
42
|
|
43
|
-
= f.show_if :category, 'Select
|
43
|
+
= f.show_if :category, 'Select up to 4' do
|
44
44
|
.card
|
45
45
|
.card-body
|
46
|
-
%h5 Select
|
47
|
-
%p Display checkboxes to select
|
46
|
+
%h5 Select up to 4 (four)
|
47
|
+
%p Display checkboxes to select up to 4 options
|
48
48
|
|
49
|
-
= f.show_if :category, 'Select
|
49
|
+
= f.show_if :category, 'Select up to 5' do
|
50
50
|
.card
|
51
51
|
.card-body
|
52
|
-
%h5 Select
|
53
|
-
%p Display checkboxes to select
|
52
|
+
%h5 Select up to 5 (five)
|
53
|
+
%p Display checkboxes to select up to 5 options
|
54
54
|
|
55
55
|
= f.show_if :category, 'Short Answer' do
|
56
56
|
.card
|
@@ -12,9 +12,13 @@
|
|
12
12
|
|
13
13
|
= tab 'Notifications' do
|
14
14
|
%p
|
15
|
-
The following email
|
15
|
+
The following email notifications will be sent to
|
16
16
|
= pluralize(poll.users.count, 'users')
|
17
17
|
in the audience.
|
18
18
|
|
19
19
|
- datatable = Admin::EffectivePollNotificationsDatatable.new(poll_id: poll.id)
|
20
20
|
= render_datatable(datatable, inline: true, simple: true)
|
21
|
+
|
22
|
+
- if poll.respond_to?(:log_changes_datatable)
|
23
|
+
= tab 'Logs' do
|
24
|
+
= render_datatable(poll.log_changes_datatable)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
= effective_form_with(model: [:admin, poll], engine: true) do |f|
|
2
|
-
= f.text_field :title, hint: 'The title of your poll.'
|
2
|
+
= f.text_field :title, hint: 'The title of your poll or election.'
|
3
3
|
|
4
|
-
= f.datetime_field :start_at, input_js: { minDate:
|
4
|
+
= f.datetime_field :start_at, input_js: { minDate: Time.zone.now.beginning_of_day.strftime('%F') }
|
5
5
|
= f.datetime_field :end_at
|
6
6
|
|
7
7
|
-# Audience
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
.row
|
2
|
+
.col-sm-6= f.date_field :date, label: false, required: poll_question.required?
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
.row
|
2
|
+
.col-sm-6= f.email_field :email, label: false, required: poll_question.required?
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
.row
|
2
|
+
.col-sm-6= f.number_field :number, label: false, required: poll_question.required?
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/app/views/effective/poll_results/results/{_select_upto_1.html.haml → _select_up_to_1.html.haml}
RENAMED
File without changes
|
data/app/views/effective/poll_results/results/{_select_upto_2.html.haml → _select_up_to_2.html.haml}
RENAMED
File without changes
|
data/app/views/effective/poll_results/results/{_select_upto_3.html.haml → _select_up_to_3.html.haml}
RENAMED
File without changes
|
data/app/views/effective/poll_results/results/{_select_upto_4.html.haml → _select_up_to_4.html.haml}
RENAMED
File without changes
|
data/app/views/effective/poll_results/results/{_select_upto_5.html.haml → _select_up_to_5.html.haml}
RENAMED
File without changes
|
data/config/effective_polls.rb
CHANGED
@@ -53,7 +53,12 @@ EffectivePolls.setup do |config|
|
|
53
53
|
#
|
54
54
|
config.mailer = {
|
55
55
|
layout: 'effective_polls_mailer_layout',
|
56
|
-
default_from: '
|
56
|
+
default_from: 'no-reply@example.com'
|
57
57
|
}
|
58
58
|
|
59
|
+
# Will work with effective_email_templates gem:
|
60
|
+
# - The poll notifications email content will be preopulated based off the template
|
61
|
+
# - Uses a EmailTemplatesMailer mailer instead of ActionMailer::Base
|
62
|
+
config.use_effective_email_templates = false
|
63
|
+
|
59
64
|
end
|
data/lib/effective_polls.rb
CHANGED
@@ -13,13 +13,13 @@ module EffectivePolls
|
|
13
13
|
mattr_accessor :ballot_response_options_table_name
|
14
14
|
|
15
15
|
mattr_accessor :authorization_method
|
16
|
-
mattr_accessor :permitted_params
|
17
16
|
|
18
17
|
mattr_accessor :layout
|
19
18
|
|
20
19
|
mattr_accessor :audience_user_scopes
|
21
20
|
|
22
21
|
# Hashes of configs
|
22
|
+
mattr_accessor :use_effective_email_templates
|
23
23
|
mattr_accessor :mailer
|
24
24
|
|
25
25
|
def self.setup
|
@@ -43,8 +43,13 @@ module EffectivePolls
|
|
43
43
|
raise Effective::AccessDenied.new('Access Denied', action, resource) unless authorized?(controller, action, resource)
|
44
44
|
end
|
45
45
|
|
46
|
-
def self.
|
47
|
-
|
46
|
+
def self.mailer_class
|
47
|
+
if use_effective_email_templates
|
48
|
+
require 'effective_email_templates'
|
49
|
+
Effective::EmailTemplatesMailer
|
50
|
+
else
|
51
|
+
ActionMailer::Base
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
55
|
end
|
@@ -26,7 +26,7 @@ module EffectivePolls
|
|
26
26
|
@poll_question_options_table_name = ':' + EffectivePolls.poll_question_options_table_name.to_s
|
27
27
|
@ballots_table_name = ':' + EffectivePolls.ballots_table_name.to_s
|
28
28
|
@ballot_responses_table_name = ':' + EffectivePolls.ballot_responses_table_name.to_s
|
29
|
-
@ballot_response_options_table_name = ':' + EffectivePolls.
|
29
|
+
@ballot_response_options_table_name = ':' + EffectivePolls.ballot_response_options_table_name.to_s
|
30
30
|
|
31
31
|
migration_template ('../' * 3) + 'db/migrate/01_create_effective_polls.rb.erb', 'db/migrate/create_effective_polls.rb'
|
32
32
|
end
|
@@ -2,29 +2,38 @@
|
|
2
2
|
|
3
3
|
class EffectivePollsMailerPreview < ActionMailer::Preview
|
4
4
|
|
5
|
-
def poll_upcoming_reminder
|
6
|
-
|
5
|
+
def poll_upcoming_reminder
|
6
|
+
poll_notification = build_poll_notification('The poll will start soon')
|
7
|
+
Effective::PollsMailer.poll_upcoming_reminder(poll_notification, build_user)
|
7
8
|
end
|
8
9
|
|
9
10
|
def poll_start
|
10
11
|
poll_notification = build_poll_notification('The poll has started')
|
11
|
-
Effective::PollsMailer.poll_start(poll_notification,
|
12
|
+
Effective::PollsMailer.poll_start(poll_notification, build_user)
|
12
13
|
end
|
13
14
|
|
14
15
|
def poll_reminder
|
15
|
-
poll_notification = build_poll_notification('
|
16
|
-
Effective::PollsMailer.poll_reminder(poll_notification,
|
16
|
+
poll_notification = build_poll_notification('The poll started already and you have not participated')
|
17
|
+
Effective::PollsMailer.poll_reminder(poll_notification, build_user)
|
17
18
|
end
|
18
19
|
|
19
20
|
def poll_end
|
20
21
|
poll_notification = build_poll_notification('The poll has ended')
|
21
|
-
Effective::PollsMailer.poll_end(poll_notification,
|
22
|
+
Effective::PollsMailer.poll_end(poll_notification, build_user)
|
22
23
|
end
|
23
24
|
|
24
25
|
protected
|
25
26
|
|
26
|
-
def
|
27
|
-
|
27
|
+
def build_user
|
28
|
+
User.new(email: 'buyer@website.com').tap do |user|
|
29
|
+
user.name = 'Valued Customer' if user.respond_to?(:name=)
|
30
|
+
user.full_name = 'Valued Customer' if user.respond_to?(:full_name=)
|
31
|
+
|
32
|
+
if user.respond_to?(:first_name=) && user.respond_to?(:last_name=)
|
33
|
+
user.first_name = 'Valued'
|
34
|
+
user.last_name = 'Customer'
|
35
|
+
end
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
39
|
def build_poll_notification(text)
|
@@ -5,17 +5,16 @@ namespace :effective_polls do
|
|
5
5
|
task notify: :environment do
|
6
6
|
poll_notifications = Effective::PollNotification.all.deep.notifiable
|
7
7
|
|
8
|
-
poll_notifications.find_each do |
|
8
|
+
poll_notifications.find_each do |notification|
|
9
9
|
begin
|
10
|
-
notified =
|
11
|
-
puts "Sent #{
|
10
|
+
notified = notification.notify!
|
11
|
+
puts "Sent #{notification.category} for #{notification.poll}" if notified
|
12
12
|
rescue => e
|
13
13
|
if defined?(ExceptionNotifier)
|
14
|
-
data
|
15
|
-
ExceptionNotifier.notify_exception(e, data: data)
|
14
|
+
ExceptionNotifier.notify_exception(e, data: { poll_notification_id: notification.id, poll_id: notification.poll_id })
|
16
15
|
end
|
17
16
|
|
18
|
-
puts "Error with effective poll_notification #{
|
17
|
+
puts "Error with effective poll_notification #{notification.id}: #{e.errors.inspect}"
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
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.1.3
|
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: 2021-
|
11
|
+
date: 2021-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -80,76 +80,6 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: sqlite3
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: devise
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: haml-rails
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: wicked
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: pry-byebug
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - ">="
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '0'
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - ">="
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: '0'
|
153
83
|
description: Online polls and user voting.
|
154
84
|
email:
|
155
85
|
- info@codeandeffect.com
|
@@ -183,11 +113,14 @@ files:
|
|
183
113
|
- app/models/effective/poll_question.rb
|
184
114
|
- app/models/effective/poll_question_option.rb
|
185
115
|
- app/views/admin/poll_notifications/_form.html.haml
|
116
|
+
- app/views/admin/poll_notifications/_form_poll_reminder.html.haml
|
117
|
+
- app/views/admin/poll_notifications/_form_poll_upcoming_reminder.html.haml
|
118
|
+
- app/views/admin/poll_notifications/_form_poll_when_poll_ends.html.haml
|
119
|
+
- app/views/admin/poll_notifications/_form_poll_when_poll_starts.html.haml
|
186
120
|
- app/views/admin/poll_questions/_form.html.haml
|
187
121
|
- app/views/admin/polls/_form.html.haml
|
188
122
|
- app/views/admin/polls/_form_content.html.haml
|
189
123
|
- app/views/admin/polls/_form_poll.html.haml
|
190
|
-
- app/views/admin/polls/_poll.html.haml
|
191
124
|
- app/views/admin/polls/results.html.haml
|
192
125
|
- app/views/effective/ballot_responses/_ballot_response.html.haml
|
193
126
|
- app/views/effective/ballot_responses/_fields.html.haml
|
@@ -197,11 +130,11 @@ files:
|
|
197
130
|
- app/views/effective/ballot_responses/fields/_long_answer.html.haml
|
198
131
|
- app/views/effective/ballot_responses/fields/_number.html.haml
|
199
132
|
- app/views/effective/ballot_responses/fields/_select_all_that_apply.html.haml
|
200
|
-
- app/views/effective/ballot_responses/fields/
|
201
|
-
- app/views/effective/ballot_responses/fields/
|
202
|
-
- app/views/effective/ballot_responses/fields/
|
203
|
-
- app/views/effective/ballot_responses/fields/
|
204
|
-
- app/views/effective/ballot_responses/fields/
|
133
|
+
- app/views/effective/ballot_responses/fields/_select_up_to_1.html.haml
|
134
|
+
- app/views/effective/ballot_responses/fields/_select_up_to_2.html.haml
|
135
|
+
- app/views/effective/ballot_responses/fields/_select_up_to_3.html.haml
|
136
|
+
- app/views/effective/ballot_responses/fields/_select_up_to_4.html.haml
|
137
|
+
- app/views/effective/ballot_responses/fields/_select_up_to_5.html.haml
|
205
138
|
- app/views/effective/ballot_responses/fields/_short_answer.html.haml
|
206
139
|
- app/views/effective/ballot_responses/fields/_upload_file.html.haml
|
207
140
|
- app/views/effective/ballot_responses/responses/_choose_one.html.haml
|
@@ -210,11 +143,11 @@ files:
|
|
210
143
|
- app/views/effective/ballot_responses/responses/_long_answer.html.haml
|
211
144
|
- app/views/effective/ballot_responses/responses/_number.html.haml
|
212
145
|
- app/views/effective/ballot_responses/responses/_select_all_that_apply.html.haml
|
213
|
-
- app/views/effective/ballot_responses/responses/
|
214
|
-
- app/views/effective/ballot_responses/responses/
|
215
|
-
- app/views/effective/ballot_responses/responses/
|
216
|
-
- app/views/effective/ballot_responses/responses/
|
217
|
-
- app/views/effective/ballot_responses/responses/
|
146
|
+
- app/views/effective/ballot_responses/responses/_select_up_to_1.html.haml
|
147
|
+
- app/views/effective/ballot_responses/responses/_select_up_to_2.html.haml
|
148
|
+
- app/views/effective/ballot_responses/responses/_select_up_to_3.html.haml
|
149
|
+
- app/views/effective/ballot_responses/responses/_select_up_to_4.html.haml
|
150
|
+
- app/views/effective/ballot_responses/responses/_select_up_to_5.html.haml
|
218
151
|
- app/views/effective/ballot_responses/responses/_short_answer.html.haml
|
219
152
|
- app/views/effective/ballot_responses/responses/_upload_file.html.haml
|
220
153
|
- app/views/effective/ballots/_ballot.html.haml
|
@@ -231,15 +164,17 @@ files:
|
|
231
164
|
- app/views/effective/poll_results/results/_number.html.haml
|
232
165
|
- app/views/effective/poll_results/results/_poll_question_option.html.haml
|
233
166
|
- app/views/effective/poll_results/results/_select_all_that_apply.html.haml
|
234
|
-
- app/views/effective/poll_results/results/
|
235
|
-
- app/views/effective/poll_results/results/
|
236
|
-
- app/views/effective/poll_results/results/
|
237
|
-
- app/views/effective/poll_results/results/
|
238
|
-
- app/views/effective/poll_results/results/
|
167
|
+
- app/views/effective/poll_results/results/_select_up_to_1.html.haml
|
168
|
+
- app/views/effective/poll_results/results/_select_up_to_2.html.haml
|
169
|
+
- app/views/effective/poll_results/results/_select_up_to_3.html.haml
|
170
|
+
- app/views/effective/poll_results/results/_select_up_to_4.html.haml
|
171
|
+
- app/views/effective/poll_results/results/_select_up_to_5.html.haml
|
239
172
|
- app/views/effective/poll_results/results/_short_answer.html.haml
|
240
173
|
- app/views/effective/poll_results/results/_upload_file.html.haml
|
241
|
-
- app/views/effective/
|
242
|
-
- app/views/effective/
|
174
|
+
- app/views/effective/polls_mailer/poll_reminder.liquid
|
175
|
+
- app/views/effective/polls_mailer/poll_upcoming_reminder.liquid
|
176
|
+
- app/views/effective/polls_mailer/poll_when_poll_ends.liquid
|
177
|
+
- app/views/effective/polls_mailer/poll_when_poll_starts.liquid
|
243
178
|
- app/views/layouts/effective_polls_mailer_layout.html.haml
|
244
179
|
- config/effective_polls.rb
|
245
180
|
- config/routes.rb
|
@@ -1,10 +0,0 @@
|
|
1
|
-
= effective_form_with(model: poll, engine: true) do |f|
|
2
|
-
= f.text_field :title, hint: 'The title of your poll.'
|
3
|
-
= f.text_area :body
|
4
|
-
|
5
|
-
= f.datetime_field :start_at
|
6
|
-
= f.datetime_field :end_at
|
7
|
-
|
8
|
-
= f.check_box :draft, hint: 'Save this poll as a draft. It will not be accessible on the website.'
|
9
|
-
|
10
|
-
= effective_submit(f)
|