effective_polls 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +132 -0
- data/Rakefile +32 -0
- data/app/assets/config/effective_polls_manifest.js +1 -0
- data/app/assets/stylesheets/effective_polls.scss +0 -0
- data/app/controllers/admin/poll_notifications_controller.rb +15 -0
- data/app/controllers/admin/poll_questions_controller.rb +15 -0
- data/app/controllers/admin/polls_controller.rb +23 -0
- data/app/controllers/effective/ballots_controller.rb +70 -0
- data/app/controllers/effective/polls_controller.rb +19 -0
- data/app/datatables/admin/effective_poll_notifications_datatable.rb +43 -0
- data/app/datatables/admin/effective_poll_questions_datatable.rb +28 -0
- data/app/datatables/admin/effective_poll_results_datatable.rb +50 -0
- data/app/datatables/admin/effective_polls_datatable.rb +29 -0
- data/app/datatables/effective_polls_datatable.rb +30 -0
- data/app/helpers/effective_polls_helper.rb +23 -0
- data/app/mailers/effective/polls_mailer.rb +23 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/ballot.rb +73 -0
- data/app/models/effective/ballot_response.rb +92 -0
- data/app/models/effective/ballot_response_option.rb +6 -0
- data/app/models/effective/poll.rb +149 -0
- data/app/models/effective/poll_notification.rb +144 -0
- data/app/models/effective/poll_question.rb +76 -0
- data/app/models/effective/poll_question_option.rb +26 -0
- data/app/views/admin/poll_notifications/_form.html.haml +55 -0
- data/app/views/admin/poll_questions/_form.html.haml +100 -0
- data/app/views/admin/polls/_form.html.haml +20 -0
- data/app/views/admin/polls/_form_content.html.haml +27 -0
- data/app/views/admin/polls/_form_poll.html.haml +32 -0
- data/app/views/admin/polls/_poll.html.haml +2 -0
- data/app/views/admin/polls/results.html.haml +6 -0
- data/app/views/effective/ballot_responses/_ballot_response.html.haml +2 -0
- data/app/views/effective/ballot_responses/_fields.html.haml +14 -0
- data/app/views/effective/ballot_responses/fields/_choose_one.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_date.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_email.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_long_answer.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_number.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_select_all_that_apply.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_select_upto_1.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_select_upto_2.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_select_upto_3.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_select_upto_4.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_select_upto_5.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_short_answer.html.haml +1 -0
- data/app/views/effective/ballot_responses/fields/_upload_file.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_choose_one.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_date.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_email.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_long_answer.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_number.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_select_all_that_apply.html.haml +5 -0
- data/app/views/effective/ballot_responses/responses/_select_upto_1.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_select_upto_2.html.haml +5 -0
- data/app/views/effective/ballot_responses/responses/_select_upto_3.html.haml +5 -0
- data/app/views/effective/ballot_responses/responses/_select_upto_4.html.haml +5 -0
- data/app/views/effective/ballot_responses/responses/_select_upto_5.html.haml +5 -0
- data/app/views/effective/ballot_responses/responses/_short_answer.html.haml +1 -0
- data/app/views/effective/ballot_responses/responses/_upload_file.html.haml +4 -0
- data/app/views/effective/ballots/_ballot.html.haml +14 -0
- data/app/views/effective/ballots/complete.html.haml +11 -0
- data/app/views/effective/ballots/start.html.haml +17 -0
- data/app/views/effective/ballots/submit.html.haml +17 -0
- data/app/views/effective/ballots/vote.html.haml +19 -0
- data/app/views/effective/poll_results/_poll_result.html.haml +2 -0
- data/app/views/effective/poll_results/_results.html.haml +38 -0
- data/app/views/effective/poll_results/results/_choose_one.html.haml +2 -0
- data/app/views/effective/poll_results/results/_date.html.haml +14 -0
- data/app/views/effective/poll_results/results/_email.html.haml +14 -0
- data/app/views/effective/poll_results/results/_long_answer.html.haml +2 -0
- data/app/views/effective/poll_results/results/_number.html.haml +14 -0
- data/app/views/effective/poll_results/results/_poll_question_option.html.haml +17 -0
- data/app/views/effective/poll_results/results/_select_all_that_apply.html.haml +2 -0
- data/app/views/effective/poll_results/results/_select_upto_1.html.haml +2 -0
- data/app/views/effective/poll_results/results/_select_upto_2.html.haml +2 -0
- data/app/views/effective/poll_results/results/_select_upto_3.html.haml +2 -0
- data/app/views/effective/poll_results/results/_select_upto_4.html.haml +2 -0
- data/app/views/effective/poll_results/results/_select_upto_5.html.haml +2 -0
- data/app/views/effective/poll_results/results/_short_answer.html.haml +2 -0
- data/app/views/effective/poll_results/results/_upload_file.html.haml +3 -0
- data/app/views/effective/polls/_form.html.haml +10 -0
- data/app/views/effective/polls/_poll.html.haml +2 -0
- data/app/views/layouts/effective_polls_mailer_layout.html.haml +7 -0
- data/config/effective_polls.rb +59 -0
- data/config/routes.rb +23 -0
- data/db/migrate/01_create_effective_polls.rb.erb +92 -0
- data/lib/effective_polls.rb +50 -0
- data/lib/effective_polls/engine.rb +11 -0
- data/lib/effective_polls/version.rb +3 -0
- data/lib/generators/effective_polls/install_generator.rb +46 -0
- data/lib/generators/templates/effective_polls_mailer_preview.rb +35 -0
- data/lib/tasks/effective_polls_tasks.rake +24 -0
- metadata +276 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class PollNotification < ActiveRecord::Base
|
|
3
|
+
belongs_to :poll
|
|
4
|
+
|
|
5
|
+
BATCHSIZE = (Rails.env.test? ? 3 : 250)
|
|
6
|
+
CATEGORIES = ['Upcoming reminder', 'When poll starts', 'Reminder', 'When poll ends']
|
|
7
|
+
|
|
8
|
+
UPCOMING_REMINDERS = {
|
|
9
|
+
'1 hour before' => 1.hours.to_i,
|
|
10
|
+
'3 hours before' => 3.hours.to_i,
|
|
11
|
+
'6 hours before' => 6.hours.to_i,
|
|
12
|
+
'12 hours before' => 12.hours.to_i,
|
|
13
|
+
'1 day before' => 1.days.to_i,
|
|
14
|
+
'2 days before' => 2.days.to_i,
|
|
15
|
+
'3 days before' => 3.days.to_i,
|
|
16
|
+
'4 days before' => 4.days.to_i,
|
|
17
|
+
'5 days before' => 5.days.to_i,
|
|
18
|
+
'6 days before' => 6.days.to_i,
|
|
19
|
+
'1 week before' => 1.weeks.to_i,
|
|
20
|
+
'2 weeks before' => 2.weeks.to_i,
|
|
21
|
+
'3 weeks before' => 3.weeks.to_i,
|
|
22
|
+
'1 month before' => 1.month.to_i
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
REMINDERS = {
|
|
26
|
+
'1 hour after' => 1.hours.to_i,
|
|
27
|
+
'3 hours after' => 3.hours.to_i,
|
|
28
|
+
'6 hours after' => 6.hours.to_i,
|
|
29
|
+
'12 hours after' => 12.hours.to_i,
|
|
30
|
+
'1 day after' => 1.days.to_i,
|
|
31
|
+
'2 days after' => 2.days.to_i,
|
|
32
|
+
'3 days after' => 3.days.to_i,
|
|
33
|
+
'4 days after' => 4.days.to_i,
|
|
34
|
+
'5 days after' => 5.days.to_i,
|
|
35
|
+
'6 days after' => 6.days.to_i,
|
|
36
|
+
'1 week after' => 1.weeks.to_i,
|
|
37
|
+
'2 weeks after' => 2.weeks.to_i,
|
|
38
|
+
'3 weeks after' => 3.weeks.to_i,
|
|
39
|
+
'1 month after' => 1.month.to_i
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
effective_resource do
|
|
43
|
+
category :string
|
|
44
|
+
reminder :integer # Number of seconds before poll.start_at
|
|
45
|
+
|
|
46
|
+
# Email
|
|
47
|
+
subject :string
|
|
48
|
+
body :text
|
|
49
|
+
|
|
50
|
+
# Tracking background jobs email send out
|
|
51
|
+
started_at :datetime
|
|
52
|
+
completed_at :datetime
|
|
53
|
+
|
|
54
|
+
timestamps
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
scope :sorted, -> { order(:id) }
|
|
58
|
+
scope :deep, -> { includes(:poll) }
|
|
59
|
+
|
|
60
|
+
scope :started, -> { where.not(started_at: nil) }
|
|
61
|
+
scope :completed, -> { where.not(completed_at: nil) }
|
|
62
|
+
|
|
63
|
+
# Called by the poll_notifier rake task
|
|
64
|
+
scope :notifiable, -> { where(started_at: nil, completed_at: nil) }
|
|
65
|
+
|
|
66
|
+
validates :poll, presence: true
|
|
67
|
+
validates :category, presence: true, inclusion: { in: CATEGORIES }
|
|
68
|
+
validates :subject, presence: true
|
|
69
|
+
validates :body, presence: true
|
|
70
|
+
|
|
71
|
+
validates :reminder, if: -> { reminder? || upcoming_reminder? },
|
|
72
|
+
presence: true, uniqueness: { scope: [:poll_id, :category], message: 'already exists' }
|
|
73
|
+
|
|
74
|
+
def to_s
|
|
75
|
+
'poll notification'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def upcoming_reminder?
|
|
79
|
+
category == 'Upcoming reminder'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def poll_start?
|
|
83
|
+
category == 'When poll starts'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def reminder?
|
|
87
|
+
category == 'Reminder'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def poll_end?
|
|
91
|
+
category == 'When poll ends'
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def notifiable?
|
|
95
|
+
started_at.blank? && completed_at.blank?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def notify_now?
|
|
99
|
+
return false unless notifiable?
|
|
100
|
+
|
|
101
|
+
case category
|
|
102
|
+
when 'When poll starts'
|
|
103
|
+
poll.available?
|
|
104
|
+
when 'When poll ends'
|
|
105
|
+
poll.ended?
|
|
106
|
+
when 'Upcoming reminder'
|
|
107
|
+
!poll.started? && poll.start_at < (Time.zone.now + reminder)
|
|
108
|
+
when 'Reminder'
|
|
109
|
+
!poll.ended? && poll.start_at < (Time.zone.now - reminder)
|
|
110
|
+
else
|
|
111
|
+
raise('unexpected category')
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def notify!
|
|
116
|
+
return false unless notify_now?
|
|
117
|
+
|
|
118
|
+
# We send to all email addresses, except for the 'Reminder' that exclude completed users
|
|
119
|
+
emails = poll.emails(exclude_completed: (category == 'Reminder'))
|
|
120
|
+
|
|
121
|
+
update_column(:started_at, Time.zone.now)
|
|
122
|
+
|
|
123
|
+
emails.in_groups_of(BATCHSIZE, false).each do |emails|
|
|
124
|
+
mail = case category
|
|
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
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
update_column(:completed_at, Time.zone.now)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class PollQuestion < ActiveRecord::Base
|
|
3
|
+
belongs_to :poll
|
|
4
|
+
|
|
5
|
+
has_many :poll_question_options, -> { order(:position) }, inverse_of: :poll_question, dependent: :delete_all
|
|
6
|
+
accepts_nested_attributes_for :poll_question_options, reject_if: :all_blank, allow_destroy: true
|
|
7
|
+
|
|
8
|
+
has_rich_text :body
|
|
9
|
+
|
|
10
|
+
CATEGORIES = [
|
|
11
|
+
'Choose one', # Radios
|
|
12
|
+
'Select all that apply', # Checks
|
|
13
|
+
'Select upto 1',
|
|
14
|
+
'Select upto 2',
|
|
15
|
+
'Select upto 3',
|
|
16
|
+
'Select upto 4',
|
|
17
|
+
'Select upto 5',
|
|
18
|
+
'Date', # Date Field
|
|
19
|
+
'Email', # Email Field
|
|
20
|
+
'Number', # Numeric Field
|
|
21
|
+
'Long Answer', # Text Area
|
|
22
|
+
'Short Answer', # Text Field
|
|
23
|
+
'Upload File' # File field
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
WITH_OPTIONS_CATEGORIES = [
|
|
27
|
+
'Choose one', # Radios
|
|
28
|
+
'Select all that apply', # Checks
|
|
29
|
+
'Select upto 1',
|
|
30
|
+
'Select upto 2',
|
|
31
|
+
'Select upto 3',
|
|
32
|
+
'Select upto 4',
|
|
33
|
+
'Select upto 5'
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
effective_resource do
|
|
37
|
+
title :string
|
|
38
|
+
category :string
|
|
39
|
+
required :boolean
|
|
40
|
+
|
|
41
|
+
position :integer
|
|
42
|
+
|
|
43
|
+
timestamps
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
before_validation(if: -> { poll.present? }) do
|
|
47
|
+
self.position ||= (poll.poll_questions.map { |obj| obj.position }.compact.max || -1) + 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
scope :deep, -> { with_rich_text_body_and_embeds.includes(:poll_question_options) }
|
|
51
|
+
scope :sorted, -> { order(:position) }
|
|
52
|
+
|
|
53
|
+
validates :title, presence: true
|
|
54
|
+
validates :category, presence: true, inclusion: { in: CATEGORIES }
|
|
55
|
+
validates :position, presence: true
|
|
56
|
+
validates :poll_question_options, presence: true, if: -> { poll_question_option? }
|
|
57
|
+
|
|
58
|
+
# Create choose_one? and select_all_that_apply? methods for each category
|
|
59
|
+
CATEGORIES.each do |category|
|
|
60
|
+
define_method(category.parameterize.underscore + '?') { self.category == category }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_s
|
|
64
|
+
title.presence || 'New Poll Question'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def poll_question_option?
|
|
68
|
+
WITH_OPTIONS_CATEGORIES.include?(category)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def category_partial
|
|
72
|
+
category.to_s.parameterize.underscore
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class PollQuestionOption < ActiveRecord::Base
|
|
3
|
+
belongs_to :poll_question
|
|
4
|
+
|
|
5
|
+
effective_resource do
|
|
6
|
+
title :text
|
|
7
|
+
position :integer
|
|
8
|
+
|
|
9
|
+
timestamps
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
before_validation(if: -> { poll_question.present? }) do
|
|
13
|
+
self.position ||= (poll_question.poll_question_options.map { |obj| obj.position }.compact.max || -1) + 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
scope :sorted, -> { order(:position) }
|
|
17
|
+
|
|
18
|
+
validates :title, presence: true
|
|
19
|
+
validates :position, presence: true
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
title.presence || 'New Poll Question Option'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
= effective_form_with(model: [:admin, poll_notification], engine: true) do |f|
|
|
2
|
+
- if inline_datatable?
|
|
3
|
+
= f.hidden_field :poll_id
|
|
4
|
+
- else
|
|
5
|
+
= f.select :poll_id, Effective::Poll.sorted.editable.all
|
|
6
|
+
|
|
7
|
+
= f.select :category, Effective::PollNotification::CATEGORIES,
|
|
8
|
+
label: 'Send an email notification'
|
|
9
|
+
|
|
10
|
+
= f.show_if :category, 'Upcoming reminder' do
|
|
11
|
+
|
|
12
|
+
= f.select :reminder, Effective::PollNotification::UPCOMING_REMINDERS, label: false,
|
|
13
|
+
hint: "before the poll starts on #{f.object.poll&.start_at&.strftime('%F')}."
|
|
14
|
+
|
|
15
|
+
.alert.alert-warning
|
|
16
|
+
%strong Upcoming Reminders
|
|
17
|
+
are sent to the entire audience before the poll starts.
|
|
18
|
+
%br
|
|
19
|
+
Use upcoming reminders to advertise, prepare, or communicate to your audience before the poll begins.
|
|
20
|
+
|
|
21
|
+
= f.show_if :category, 'When poll starts' do
|
|
22
|
+
.alert.alert-warning
|
|
23
|
+
%strong When poll starts
|
|
24
|
+
notifications will be sent within 10 minutes of the poll start time.
|
|
25
|
+
|
|
26
|
+
= f.show_if :category, 'Reminder' do
|
|
27
|
+
|
|
28
|
+
= f.select :reminder, Effective::PollNotification::REMINDERS, label: false,
|
|
29
|
+
hint: "after the poll starts on #{f.object.poll&.start_at&.strftime('%F')}."
|
|
30
|
+
|
|
31
|
+
.alert.alert-warning
|
|
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.
|
|
36
|
+
|
|
37
|
+
= f.show_if :category, 'When poll ends' do
|
|
38
|
+
.alert.alert-warning
|
|
39
|
+
%strong When poll ends
|
|
40
|
+
notifications will be sent within 10 minutes of the poll end time.
|
|
41
|
+
|
|
42
|
+
= f.text_field :subject, label: 'Email Subject'
|
|
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)
|
|
54
|
+
|
|
55
|
+
= effective_submit(f)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
= effective_form_with(model: [:admin, poll_question], engine: true) do |f|
|
|
2
|
+
- if inline_datatable?
|
|
3
|
+
= f.hidden_field :poll_id
|
|
4
|
+
- else
|
|
5
|
+
= f.select :poll_id, Effective::Poll.sorted.editable.all
|
|
6
|
+
|
|
7
|
+
= f.text_field :title, label: 'Question Title'
|
|
8
|
+
= f.rich_text_area :body, label: 'Body (optional)'
|
|
9
|
+
|
|
10
|
+
= f.check_box :required, hint: 'A response to this question will be required'
|
|
11
|
+
= f.select :category, Effective::PollQuestion::CATEGORIES
|
|
12
|
+
|
|
13
|
+
= f.show_if :category, 'Choose one' do
|
|
14
|
+
.card
|
|
15
|
+
.card-body
|
|
16
|
+
%h5 Choose one
|
|
17
|
+
%p Display radio buttons to choose one option
|
|
18
|
+
|
|
19
|
+
= f.show_if :category, 'Select all that apply' do
|
|
20
|
+
.card
|
|
21
|
+
.card-body
|
|
22
|
+
%h5 Select all that apply
|
|
23
|
+
%p Display checkboxes to select all options that apply
|
|
24
|
+
|
|
25
|
+
= f.show_if :category, 'Select upto 1' do
|
|
26
|
+
.card
|
|
27
|
+
.card-body
|
|
28
|
+
%h5 Select upto 1 (one)
|
|
29
|
+
%p Display checkboxes to select upto 1 option
|
|
30
|
+
|
|
31
|
+
= f.show_if :category, 'Select upto 2' do
|
|
32
|
+
.card
|
|
33
|
+
.card-body
|
|
34
|
+
%h5 Select upto 2 (two)
|
|
35
|
+
%p Display checkboxes to select upto 2 options
|
|
36
|
+
|
|
37
|
+
= f.show_if :category, 'Select upto 3' do
|
|
38
|
+
.card
|
|
39
|
+
.card-body
|
|
40
|
+
%h5 Select upto 3 (three)
|
|
41
|
+
%p Display checkboxes to select upto 3 options
|
|
42
|
+
|
|
43
|
+
= f.show_if :category, 'Select upto 4' do
|
|
44
|
+
.card
|
|
45
|
+
.card-body
|
|
46
|
+
%h5 Select upto 4 (four)
|
|
47
|
+
%p Display checkboxes to select upto 4 options
|
|
48
|
+
|
|
49
|
+
= f.show_if :category, 'Select upto 5' do
|
|
50
|
+
.card
|
|
51
|
+
.card-body
|
|
52
|
+
%h5 Select upto 5 (five)
|
|
53
|
+
%p Display checkboxes to select upto 5 options
|
|
54
|
+
|
|
55
|
+
= f.show_if :category, 'Short Answer' do
|
|
56
|
+
.card
|
|
57
|
+
.card-body
|
|
58
|
+
%h5 Short Answer
|
|
59
|
+
%p Display a text field to enter a short text answer
|
|
60
|
+
|
|
61
|
+
= f.show_if :category, 'Long Answer' do
|
|
62
|
+
.card
|
|
63
|
+
.card-body
|
|
64
|
+
%h5 Long Answer
|
|
65
|
+
%p Display a textarea to enter a long text answer
|
|
66
|
+
|
|
67
|
+
= f.show_if :category, 'Date' do
|
|
68
|
+
.card
|
|
69
|
+
.card-body
|
|
70
|
+
%h5 Date
|
|
71
|
+
%p Display a date field to enter a date
|
|
72
|
+
|
|
73
|
+
= f.show_if :category, 'Email' do
|
|
74
|
+
.card
|
|
75
|
+
.card-body
|
|
76
|
+
%h5 Email
|
|
77
|
+
%p Display an email field to enter an email
|
|
78
|
+
|
|
79
|
+
= f.show_if :category, 'Number' do
|
|
80
|
+
.card
|
|
81
|
+
.card-body
|
|
82
|
+
%h5 Number
|
|
83
|
+
%p Display a number field to enter an integer number
|
|
84
|
+
|
|
85
|
+
= f.show_if :category, 'Upload File' do
|
|
86
|
+
.card
|
|
87
|
+
.card-body
|
|
88
|
+
%h5 Upload File
|
|
89
|
+
%p Display a file field to upload a file
|
|
90
|
+
|
|
91
|
+
= f.show_if_any :category, Effective::PollQuestion::WITH_OPTIONS_CATEGORIES do
|
|
92
|
+
.mt-3.card
|
|
93
|
+
.card-body
|
|
94
|
+
%h5 Options
|
|
95
|
+
%p Display the following options:
|
|
96
|
+
|
|
97
|
+
= f.has_many :poll_question_options, class: 'tight' do |fa|
|
|
98
|
+
= fa.text_field :title, label: false
|
|
99
|
+
|
|
100
|
+
= effective_submit(f)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
= tabs do
|
|
2
|
+
= tab 'Poll' do
|
|
3
|
+
= render 'admin/polls/form_poll', poll: poll
|
|
4
|
+
|
|
5
|
+
- if poll.persisted?
|
|
6
|
+
= tab 'Content' do
|
|
7
|
+
= render 'admin/polls/form_content', poll: poll
|
|
8
|
+
|
|
9
|
+
= tab 'Questions' do
|
|
10
|
+
- datatable = Admin::EffectivePollQuestionsDatatable.new(poll_id: poll.id)
|
|
11
|
+
= render_datatable(datatable, inline: true, simple: true)
|
|
12
|
+
|
|
13
|
+
= tab 'Notifications' do
|
|
14
|
+
%p
|
|
15
|
+
The following email notification will be sent to all
|
|
16
|
+
= pluralize(poll.users.count, 'users')
|
|
17
|
+
in the audience.
|
|
18
|
+
|
|
19
|
+
- datatable = Admin::EffectivePollNotificationsDatatable.new(poll_id: poll.id)
|
|
20
|
+
= render_datatable(datatable, inline: true, simple: true)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
= 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'
|
|
6
|
+
|
|
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'
|
|
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'
|
|
16
|
+
|
|
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'
|
|
21
|
+
|
|
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'
|
|
26
|
+
|
|
27
|
+
= f.submit
|