effective_polls 0.2.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +2 -2
  4. data/Rakefile +5 -19
  5. data/app/controllers/admin/polls_controller.rb +1 -7
  6. data/app/controllers/effective/ballots_controller.rb +4 -1
  7. data/app/datatables/admin/effective_poll_notifications_datatable.rb +4 -1
  8. data/app/datatables/admin/effective_poll_results_datatable.rb +1 -4
  9. data/app/datatables/admin/effective_polls_datatable.rb +1 -0
  10. data/app/datatables/{effective_polls_datatable.rb → effective_polls_available_polls_datatable.rb} +6 -4
  11. data/app/helpers/effective_polls_helper.rb +17 -13
  12. data/app/mailers/effective/polls_mailer.rb +3 -1
  13. data/app/models/concerns/effective_polls_user.rb +67 -0
  14. data/app/models/effective/ballot.rb +11 -2
  15. data/app/models/effective/ballot_response.rb +1 -1
  16. data/app/models/effective/poll.rb +39 -26
  17. data/app/models/effective/poll_notification.rb +2 -2
  18. data/app/models/effective/poll_question.rb +1 -1
  19. data/app/models/effective/poll_question_option.rb +1 -1
  20. data/app/views/admin/poll_notifications/_form.html.haml +3 -5
  21. data/app/views/admin/poll_questions/_form.html.haml +12 -5
  22. data/app/views/admin/polls/_form.html.haml +10 -5
  23. data/app/views/admin/polls/_form_content.html.haml +16 -20
  24. data/app/views/admin/polls/_form_poll.html.haml +16 -7
  25. data/app/views/admin/polls/_poll.html.haml +5 -0
  26. data/app/views/effective/ballots/_content.html.haml +10 -0
  27. data/app/views/effective/ballots/_layout.html.haml +3 -0
  28. data/app/views/effective/ballots/complete.html.haml +13 -8
  29. data/app/views/effective/ballots/start.html.haml +29 -12
  30. data/app/views/effective/ballots/submit.html.haml +10 -13
  31. data/app/views/effective/ballots/vote.html.haml +10 -15
  32. data/app/views/effective/poll_results/_results.html.haml +2 -2
  33. data/app/views/effective/polls/_dashboard.html.haml +25 -0
  34. data/app/views/effective/polls_mailer/poll_before_poll_ends.liquid +0 -1
  35. data/app/views/effective/polls_mailer/poll_reminder.liquid +0 -1
  36. data/app/views/effective/polls_mailer/poll_upcoming_reminder.liquid +0 -1
  37. data/app/views/effective/polls_mailer/poll_when_poll_ends.liquid +0 -1
  38. data/app/views/effective/polls_mailer/poll_when_poll_starts.liquid +0 -1
  39. data/config/effective_polls.rb +2 -19
  40. data/config/locales/effective_polls.yml +14 -0
  41. data/config/routes.rb +2 -5
  42. data/db/migrate/{01_create_effective_polls.rb.erb → 101_create_effective_polls.rb} +19 -17
  43. data/db/seeds.rb +36 -0
  44. data/lib/effective_polls/engine.rb +7 -0
  45. data/lib/effective_polls/version.rb +1 -1
  46. data/lib/effective_polls.rb +2 -4
  47. data/lib/generators/effective_polls/install_generator.rb +1 -9
  48. data/lib/tasks/effective_polls_tasks.rake +23 -12
  49. metadata +144 -12
  50. 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: 57df19aaa933dd133ba655525265e129ca1c2bd7a60a78a5a8f2fe89ec1aa5cc
4
- data.tar.gz: 86fe4a6defeef051e4ff9c8543480fd6db703e213d80cf100781f4c71cc60e4b
3
+ metadata.gz: 637320f25a72489ada773806629e70590bb5c8435e871a6de40497e2eb6300ed
4
+ data.tar.gz: e797d1afdad6be66099b291ec7a809cbb65ef32d7963ca04f03d3ac3d91fe2a9
5
5
  SHA512:
6
- metadata.gz: 1b6f6ace193a55d55b49184f8a2b9a1a0766b0e1249c5c3daa65bfac034a7bb7b8ae1920b66ed04d1605137a88798d749951f0f714e2289774f63dfc5d820ca4
7
- data.tar.gz: e0b94cefd83a9af17f232cedc37369615ed0042543b886a496174fd807a3117cab3a876bcb6eb34d61f2ca50a70ede2c2c92d965df67d4b0619dc9a3fd05f052
6
+ metadata.gz: 7317013d4063bdd11eaf4a72b6d5ca964c7acb2c35ac29653e9c7043c4e4c40de4e1b4b55079ed023b758f08982a51ca17926e37c5abafbca2462cf0b4a9e657
7
+ data.tar.gz: d3fe9a3b04a9ca98c5a27fa956fb82d536db6b9662b6d61a0e8fd954f603673384f6d70c3ec33e51fabde548063b126892508e858be72e616d2c9ff30318e732
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2021 Code and Effect Inc.
1
+ Copyright 2023 Code and Effect Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -10,7 +10,7 @@ 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.
13
+ This requires Rails 6 and Twitter Bootstrap 4 and just works with Devise.
14
14
 
15
15
  Please first install the [effective_datatables](https://github.com/code-and-effect/effective_datatables) gem.
16
16
 
@@ -19,7 +19,7 @@ Please download and install the [Twitter Bootstrap4](http://getbootstrap.com)
19
19
  Add to your Gemfile:
20
20
 
21
21
  ```ruby
22
- gem 'haml-rails' # or try using gem 'hamlit-rails'
22
+ gem 'haml'
23
23
  gem 'effective_polls'
24
24
  ```
25
25
 
data/Rakefile CHANGED
@@ -1,27 +1,13 @@
1
- begin
2
- require 'bundler/setup'
3
- rescue LoadError
4
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
- end
6
-
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'EffectivePolls'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.md')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
1
+ require "bundler/setup"
16
2
 
17
3
  APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
- load 'rails/tasks/engine.rake'
4
+ load "rails/tasks/engine.rake"
19
5
 
20
- load 'rails/tasks/statistics.rake'
6
+ load "rails/tasks/statistics.rake"
21
7
 
22
- require 'bundler/gem_tasks'
8
+ require "bundler/gem_tasks"
23
9
 
24
- require 'rake/testtask'
10
+ require "rake/testtask"
25
11
 
26
12
  Rake::TestTask.new(:test) do |t|
27
13
  t.libs << 'test'
@@ -5,13 +5,7 @@ module Admin
5
5
 
6
6
  include Effective::CrudController
7
7
 
8
- def results
9
- @poll = Effective::Poll.find(params[:id])
10
- EffectiveResources.authorize!(self, :results, @poll)
11
-
12
- @datatable = Admin::EffectivePollResultsDatatable.new(poll_token: @poll.token)
13
- @page_title = "#{@poll} Results"
14
- end
8
+ on :save, only: :create, redirect: :edit
15
9
 
16
10
  def permitted_params
17
11
  params.require(:effective_poll).permit!
@@ -1,6 +1,9 @@
1
1
  module Effective
2
2
  class BallotsController < ApplicationController
3
- before_action(:authenticate_user!) if defined?(Devise)
3
+
4
+ if defined?(Devise)
5
+ before_action :authenticate_user!, unless: -> { action_name == 'new' || (action_name == 'show' && params[:id] == 'start') }
6
+ end
4
7
 
5
8
  include Effective::WizardController
6
9
 
@@ -31,7 +31,10 @@ class Admin::EffectivePollNotificationsDatatable < Effective::Datatable
31
31
  end
32
32
 
33
33
  col :subject
34
- col :body
34
+
35
+ col :body do |notification|
36
+ simple_format(notification.body.to_s)
37
+ end
35
38
 
36
39
  col :started_at, visible: false
37
40
  col :completed_at
@@ -41,10 +41,7 @@ class Admin::EffectivePollResultsDatatable < Effective::Datatable
41
41
  end
42
42
 
43
43
  def poll
44
- @poll ||= begin
45
- raise('expected datatable poll_token attribute') unless attributes[:poll_token]
46
- Effective::Poll.deep_results.find(attributes[:poll_token])
47
- end
44
+ @poll ||= Effective::Poll.deep_results.where(id: attributes[:poll_id]).first!
48
45
  end
49
46
 
50
47
  end
@@ -18,6 +18,7 @@ class Admin::EffectivePollsDatatable < Effective::Datatable
18
18
  col :end_at
19
19
  col :audience
20
20
 
21
+ col :poll_notifications
21
22
  col :poll_questions, visible: false
22
23
 
23
24
  actions_col
@@ -1,13 +1,14 @@
1
+ # Dashboard available polls
1
2
  # Displays available polls that the current_user may complete
2
3
 
3
- class EffectivePollsDatatable < Effective::Datatable
4
+ class EffectivePollsAvailablePollsDatatable < Effective::Datatable
4
5
  datatable do
5
6
  order :start_at
6
7
 
7
8
  col :start_at, visible: false
8
9
 
9
10
  col :title
10
- col :available_date, label: 'Date'
11
+ col :available_date
11
12
 
12
13
  actions_col(actions: []) do |poll|
13
14
  ballot = poll.ballots.where(user: current_user).first
@@ -15,16 +16,17 @@ class EffectivePollsDatatable < Effective::Datatable
15
16
  if ballot.blank?
16
17
  dropdown_link_to('Start', effective_polls.poll_ballot_build_path(poll, :new, :start))
17
18
  elsif ballot.completed?
19
+ #dropdown_link_to('Show', effective_polls.poll_ballot_path(poll, ballot))
18
20
  'Complete'
19
21
  else
20
22
  dropdown_link_to('Continue', effective_polls.poll_ballot_build_path(poll, ballot, ballot.next_step))
23
+ dropdown_link_to('Delete', effective_polls.poll_ballot_path(poll, ballot), 'data-confirm': "Really delete #{ballot}?", 'data-method': :delete)
21
24
  end
22
25
  end
23
26
  end
24
27
 
25
28
  collection do
26
- raise('expected a current_user') unless current_user.present?
27
- Effective::Poll.available.select { |poll| poll.available_for?(current_user) }
29
+ Effective::Poll.where(id: current_user.available_polls)
28
30
  end
29
31
 
30
32
  end
@@ -1,22 +1,26 @@
1
1
  module EffectivePollsHelper
2
2
 
3
+ # Used on dashboard
4
+ def polls_name_label
5
+ et('effective_polls.name')
6
+ end
7
+
3
8
  # Used by admin/polls form
4
- def effective_polls_audience_scope_collection
5
- # Normalize the collection into [[label, value], [label, value]]
6
- scopes = Array(EffectivePolls.audience_user_scopes).map do |key, value|
7
- (key.present? && value.present?) ? [key, value] : [key.to_s.titleize, key]
8
- end
9
+ def effective_polls_audience_scope_collection(poll)
10
+ klass = poll.try(:audience_class)
11
+ raise('expected a poll with an audience_class') unless klass.try(:effective_polls_user?)
9
12
 
10
- # Makes sure the User model responds to all values
11
- scopes.each do |_, scope|
12
- unless defined?(User) && User.respond_to?(scope)
13
- raise("invalid effective_polls config.audience_user_scopes value. The user model must respond to the scope User.#{scope}")
14
- end
15
- end
13
+ resource = klass.new
14
+
15
+ scopes = resource.poll_audience_scopes
16
+ raise('expected poll audience scopes') unless scopes.kind_of?(Array)
16
17
 
17
18
  # Append the number of users in this scope
18
- scopes.map! do |label, scope|
19
- ["#{label} (#{pluralize(User.send(scope).count, 'user')})", scope]
19
+ scopes.map do |label, scope|
20
+ relation = resource.poll_audience_scope(scope)
21
+ raise("invalid poll_audience_scope for #{scope}") unless relation.kind_of?(ActiveRecord::Relation)
22
+
23
+ ["#{label} (#{pluralize(relation.count, 'user')})", scope]
20
24
  end
21
25
  end
22
26
 
@@ -75,7 +75,9 @@ module Effective
75
75
  title: poll.title,
76
76
  url: effective_polls.poll_url(poll),
77
77
  user: {
78
- name: user.to_s,
78
+ name: (user.try(:email_to_s) || user.to_s),
79
+ first_name: user.try(:first_name).to_s,
80
+ last_name: user.try(:last_name).to_s,
79
81
  email: user.email
80
82
  }
81
83
  }
@@ -0,0 +1,67 @@
1
+ # EffectivePollsUser
2
+ #
3
+ # Mark your user model with effective_polls_user to get all the includes
4
+
5
+ module EffectivePollsUser
6
+ extend ActiveSupport::Concern
7
+
8
+ module Base
9
+ def effective_polls_user
10
+ include ::EffectivePollsUser
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ def effective_polls_user?; true; end
16
+ end
17
+
18
+ included do
19
+ has_many :ballots, -> { Effective::Ballot.sorted }, inverse_of: :user, as: :user, class_name: 'Effective::Ballot'
20
+ end
21
+
22
+ # The list of all available audience scopes for the Poll Selected Users
23
+ def poll_audience_scopes
24
+ scopes = [
25
+ ['All Users', :all]
26
+ ]
27
+
28
+ if self.class.try(:effective_memberships_user?)
29
+ scopes += [
30
+ ['All members', :members],
31
+ ['All removed members', :membership_removed],
32
+ ['All members in good standing', :membership_in_good_standing],
33
+ ['All members not in good standing', :membership_not_in_good_standing],
34
+ ['All members renewed this period', :membership_renewed_this_period],
35
+ ]
36
+
37
+ scopes += EffectiveMemberships.Category.sorted.map do |category|
38
+ ["All #{category} members", "members_with_category_id_#{category.id}"]
39
+ end
40
+ end
41
+
42
+ scopes
43
+ end
44
+
45
+ # Turns the given audience_scope value into the actual ActiveRecord::Relation scope
46
+ def poll_audience_scope(value)
47
+ collection = self.class.respond_to?(:unarchived) ? self.class.unarchived : self.class
48
+
49
+ # If we respond to the fill value, call it
50
+ return collection.send(value) if collection.respond_to?(value)
51
+
52
+ # Parse the value
53
+ name, id = value.to_s.split('_id_')
54
+
55
+ case name.try(:to_sym)
56
+ when :members_with_category
57
+ collection.members_with_category(EffectiveMemberships.Category.find(id))
58
+ else
59
+ raise("unknown poll_audience_scope for #{value}")
60
+ end
61
+ end
62
+
63
+ def available_polls
64
+ Effective::Poll.available.select { |poll| poll.available_for?(self) }
65
+ end
66
+
67
+ end
@@ -3,14 +3,19 @@ module Effective
3
3
  attr_accessor :current_user
4
4
  attr_accessor :current_step
5
5
 
6
+ # Application namespace
7
+ belongs_to :user, polymorphic: true
8
+
9
+ # Effective namespace
6
10
  belongs_to :poll
7
- belongs_to :user
8
11
 
9
12
  has_many :ballot_responses, dependent: :destroy
10
13
  accepts_nested_attributes_for :ballot_responses
11
14
 
12
15
  acts_as_tokened
13
16
 
17
+ log_changes(to: :poll) if respond_to?(:log_changes)
18
+
14
19
  acts_as_wizard(
15
20
  start: 'Start',
16
21
  vote: 'Ballot',
@@ -34,6 +39,10 @@ module Effective
34
39
 
35
40
  scope :deep, -> { includes(:poll, :user, ballot_responses: [:poll, :poll_question, :poll_question_options]) }
36
41
  scope :sorted, -> { order(:id) }
42
+
43
+ scope :in_progress, -> { where(completed_at: nil) }
44
+ scope :done, -> { where.not(completed_at: nil) }
45
+
37
46
  scope :completed, -> { where.not(completed_at: nil) }
38
47
 
39
48
  before_validation(if: -> { new_record? }) do
@@ -48,7 +57,7 @@ module Effective
48
57
  validates :ballot_responses, associated: true
49
58
 
50
59
  def to_s
51
- 'ballot'
60
+ model_name.human
52
61
  end
53
62
 
54
63
  # Find or build
@@ -64,7 +64,7 @@ module Effective
64
64
  length: { maximum: 5, message: 'please select 5 options or fewer' }
65
65
 
66
66
  def to_s
67
- 'ballot reponse'
67
+ model_name.human
68
68
  end
69
69
 
70
70
  def response
@@ -1,10 +1,6 @@
1
1
  module Effective
2
2
  class Poll < ActiveRecord::Base
3
- has_rich_text :all_steps_content
4
- has_rich_text :start_content
5
- has_rich_text :vote_content
6
- has_rich_text :submit_content
7
- has_rich_text :complete_content
3
+ acts_as_tokened
8
4
 
9
5
  has_many :poll_notifications, -> { order(:id) }, inverse_of: :poll, dependent: :destroy
10
6
  accepts_nested_attributes_for :poll_notifications, allow_destroy: true
@@ -19,7 +15,12 @@ module Effective
19
15
  has_many :completed_ballots, -> { Effective::Ballot.completed }, class_name: 'Effective::Ballot'
20
16
  has_many :completed_ballot_responses, -> { where(ballot: Effective::Ballot.completed) }, class_name: 'Effective::BallotResponse'
21
17
 
22
- acts_as_tokened
18
+ has_many_rich_texts
19
+ # rich_text_all_steps_content
20
+ # rich_text_start_content
21
+ # rich_text_vote_content
22
+ # rich_text_submit_content
23
+ # rich_text_complete_content
23
24
 
24
25
  if respond_to?(:log_changes)
25
26
  log_changes(except: [:ballots, :ballot_responses, :completed_ballots, :completed_ballot_responses])
@@ -29,29 +30,23 @@ module Effective
29
30
 
30
31
  effective_resource do
31
32
  # Acts as tokened
32
- token :string, permitted: false
33
+ token :string, permitted: false
33
34
 
34
35
  title :string
35
36
 
36
37
  start_at :datetime
37
38
  end_at :datetime
38
39
 
39
- audience :string
40
- audience_scope :text # An Array of user_ids or named scopes on the User model
40
+ audience :string
41
+ audience_class_name :string
42
+ audience_scope :text # An Array of user_ids or named scopes on the User model
41
43
 
42
44
  timestamps
43
45
  end
44
46
 
45
47
  serialize :audience_scope, Array
46
48
 
47
- scope :deep, -> {
48
- includes(poll_questions: :poll_question_options)
49
- .with_rich_text_all_steps_content
50
- .with_rich_text_start_content
51
- .with_rich_text_vote_content
52
- .with_rich_text_submit_content
53
- .with_rich_text_complete_content
54
- }
49
+ scope :deep, -> { includes(poll_questions: :poll_question_options) }
55
50
 
56
51
  scope :deep_results, -> {
57
52
  includes(poll_questions: :poll_question_options)
@@ -68,6 +63,8 @@ module Effective
68
63
  validates :start_at, presence: true
69
64
 
70
65
  validates :audience, inclusion: { in: AUDIENCES }
66
+ validates :audience_class_name, presence: true
67
+
71
68
  validates :audience_scope, presence: true, unless: -> { audience == 'All Users' }
72
69
 
73
70
  validate(if: -> { start_at.present? && end_at.present? }) do
@@ -75,33 +72,49 @@ module Effective
75
72
  end
76
73
 
77
74
  def to_s
78
- title.presence || 'New Poll'
75
+ title.presence || model_name.human
79
76
  end
80
77
 
81
78
  def available_for?(user)
82
- raise('expected a user') unless user.kind_of?(User)
79
+ raise('expected an effective_polls_user') unless user.class.try(:effective_polls_user?)
83
80
  available? && users.include?(user)
84
81
  end
85
82
 
83
+ def audience_class
84
+ klass = audience_class_name.safe_constantize
85
+ raise('expected an effective_polls_user klass') unless klass.try(:effective_polls_user?)
86
+ klass
87
+ end
88
+
86
89
  def users(except_completed: false)
90
+ klass = audience_class()
91
+ resource = klass.new
92
+
87
93
  users = case audience
88
94
  when 'All Users'
89
- User.all
95
+ klass.try(:unarchived) || klass.all
90
96
  when 'Individual Users'
91
- User.where(id: audience_scope)
97
+ (klass.try(:unarchived) || klass.all).where(id: audience_scope)
92
98
  when 'Selected Users'
93
- collection = User.none
94
- audience_scope.each { |scope| collection = collection.or(User.send(scope)) }
99
+ collection = klass.none
100
+
101
+ audience_scope.each do |scope|
102
+ relation = resource.poll_audience_scope(scope)
103
+ raise("invalid poll_audience_scope for #{scope}") unless relation.kind_of?(ActiveRecord::Relation)
104
+
105
+ collection = collection.or(relation)
106
+ end
107
+
95
108
  collection
96
109
  else
97
110
  raise('unexpected audience')
98
111
  end
99
112
 
100
113
  if except_completed
101
- users.where.not(id: completed_ballots.select('user_id as id'))
102
- else
103
- users
114
+ users = users.where.not(id: completed_ballots.select('user_id as id'))
104
115
  end
116
+
117
+ users
105
118
  end
106
119
 
107
120
  def available?
@@ -72,7 +72,7 @@ module Effective
72
72
  validates :subject, presence: true
73
73
  validates :body, presence: true
74
74
 
75
- if EffectivePolls.use_effective_email_templates
75
+ with_options(if: -> { EffectivePolls.use_effective_email_templates }) do
76
76
  validates :body, liquid: true
77
77
  validates :subject, liquid: true
78
78
  end
@@ -81,7 +81,7 @@ module Effective
81
81
  presence: true, uniqueness: { scope: [:poll_id, :category], message: 'already exists' }
82
82
 
83
83
  def to_s
84
- 'poll notification'
84
+ [category.presence, subject.presence].compact.join(' - ') || model_name.human
85
85
  end
86
86
 
87
87
  def email_template
@@ -62,7 +62,7 @@ module Effective
62
62
  end
63
63
 
64
64
  def to_s
65
- title.presence || 'New Poll Question'
65
+ title.presence || model_name.human
66
66
  end
67
67
 
68
68
  def poll_question_option?
@@ -19,7 +19,7 @@ module Effective
19
19
  validates :position, presence: true
20
20
 
21
21
  def to_s
22
- title.presence || 'New Poll Question Option'
22
+ title.presence || model_name.human
23
23
  end
24
24
 
25
25
  end
@@ -12,22 +12,20 @@
12
12
  - template = 'poll_' + category.parameterize.underscore
13
13
 
14
14
  = f.show_if :category, category do
15
- = render "/admin/poll_notifications/form_#{template}", f: f
15
+ .my-3= render "/admin/poll_notifications/form_#{template}", f: f
16
+
17
+ = f.select :from, EffectivePolls.mailer_froms
16
18
 
17
19
  - if f.object.category == category
18
- = f.email_field :from
19
20
  = f.text_field :subject
20
21
  = f.text_area :body, rows: 10
21
22
 
22
23
  - elsif EffectivePolls.use_effective_email_templates == false
23
- = f.email_field :from, value: EffectivePolls.mailer[:default_from]
24
24
  = f.text_field :subject, value: ''
25
25
  = f.text_area :body, rows: 10, value: ''
26
26
 
27
27
  - else
28
28
  - email_template = Effective::EmailTemplate.where(template_name: template).first!
29
-
30
- = f.email_field :from, value: email_template.from
31
29
  = f.text_field :subject, value: email_template.subject
32
30
  = f.text_area :body, rows: 10, value: email_template.body
33
31
 
@@ -2,19 +2,26 @@
2
2
  - if inline_datatable?
3
3
  = f.hidden_field :poll_id
4
4
  - else
5
- = f.select :poll_id, Effective::Poll.sorted.editable.all
5
+ = f.select :poll_id, Effective::Poll.all
6
6
 
7
7
  = f.text_field :title, label: 'Question Title'
8
- = f.rich_text_area :body, label: 'Body (optional)'
8
+
9
+ - if defined?(EffectiveArticleEditor)
10
+ = f.article_editor :body, label: 'Body (optional)'
11
+ - else
12
+ = f.rich_text_area :body, label: 'Body (optional)'
9
13
 
10
14
  = f.check_box :required, hint: 'A response to this question will be required'
11
15
  = f.select :category, Effective::PollQuestion::CATEGORIES
12
16
 
13
17
  = f.show_if :category, 'Choose one' do
14
- .card
18
+ .mt-3.card
15
19
  .card-body
16
- %h5 Choose one
17
- %p Display radio buttons to choose one option
20
+ %h5 Options
21
+ %p Display the following options:
22
+
23
+ = f.has_many :poll_question_options, build: true do |fa|
24
+ = fa.text_field :title, label: false
18
25
 
19
26
  = f.show_if :category, 'Select all that apply' do
20
27
  .card
@@ -7,18 +7,23 @@
7
7
  = render 'admin/polls/form_content', poll: poll
8
8
 
9
9
  = tab 'Questions' do
10
- - datatable = Admin::EffectivePollQuestionsDatatable.new(poll_id: poll.id)
10
+ - datatable = Admin::EffectivePollQuestionsDatatable.new(poll: poll)
11
11
  = render_datatable(datatable, inline: true, simple: true)
12
12
 
13
13
  = tab 'Notifications' do
14
14
  %p
15
15
  The following email notifications will be sent to
16
- = pluralize(poll.users.count, 'users')
16
+ = pluralize(poll.users.count, 'user')
17
17
  in the audience.
18
18
 
19
- - datatable = Admin::EffectivePollNotificationsDatatable.new(poll_id: poll.id)
19
+ %p
20
+ The url for this #{et(poll)} is:
21
+ - url = effective_polls.poll_url(poll)
22
+ = link_to(url, url, target: '_blank')
23
+
24
+ - datatable = Admin::EffectivePollNotificationsDatatable.new(poll: poll)
20
25
  = render_datatable(datatable, inline: true, simple: true)
21
26
 
22
- - if poll.respond_to?(:log_changes_datatable)
27
+ - if poll.respond_to?(:logs_datatable)
23
28
  = tab 'Logs' do
24
- = render_datatable(poll.log_changes_datatable)
29
+ = render_datatable(poll.logs_datatable)
@@ -1,27 +1,23 @@
1
+ %p Each of the following content areas will be displayed on the ballot wizard.
2
+
1
3
  = effective_form_with(model: [:admin, poll], engine: true) do |f|
2
- .card.mb-4
3
- .card-body
4
- %h5.card-title All Steps Content
5
- = f.rich_text_area :all_steps_content, label: false, hint: 'displayed on all ballot steps'
4
+ = card("All Steps") do
5
+ - if defined?(EffectiveArticleEditor)
6
+ = f.article_editor "rich_text_all_steps_content", label: false, hint: "displayed on all steps"
7
+ - else
8
+ = f.rich_text_area "rich_text_all_steps_content", label: false, hint: "displayed on all steps"
6
9
 
7
- .card.mb-4
8
- .card-body
9
- %h5.card-title Start Step
10
- = f.rich_text_area :start_content, label: false, hint: 'displayed on the start step only'
10
+ %hr
11
11
 
12
- .card.mb-4
13
- .card-body
14
- %h5.card-title Vote Step
15
- = f.rich_text_area :vote_content, label: false, hint: 'displayed on the vote step only'
12
+ - enabled = Effective::Ballot.all_wizard_steps
16
13
 
17
- .card.mb-4
18
- .card-body
19
- %h5.card-title Review and Submit Step
20
- = f.rich_text_area :submit_content, label: false, hint: 'displayed on the review and submit step only'
14
+ - Effective::Ballot::WIZARD_STEPS.each do |step, title|
15
+ - next unless enabled.include?(step)
21
16
 
22
- .card.mb-4
23
- .card-body
24
- %h5.card-title Complete Step
25
- = f.rich_text_area :complete_content, label: false, hint: 'displayed on the complete step only'
17
+ = card("#{title}") do
18
+ - if defined?(EffectiveArticleEditor)
19
+ = f.article_editor "rich_text_#{step}_content", label: false, hint: "displayed on the ballot #{step} wizard step only"
20
+ - else
21
+ = f.rich_text_area "rich_text_#{step}_content", label: false, hint: "displayed on the ballot #{step} wizard step only"
26
22
 
27
23
  = f.submit