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
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b49f5df5989ddd470b3090d2ac28ab5974e902bd33f8a57e05487025074cf0a8
|
|
4
|
+
data.tar.gz: f3465afeb7bee7279348f24f7e85128d136cac9d47add5f3c67f8a1ee740062f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5ea3cf981517d7d8081feae614b054114f156826b5a694410d48f3418b7cf9df2db606c290d3f89a9ca1018ff4a8c64550528b9071436d7c7c02c863217467d1
|
|
7
|
+
data.tar.gz: 76898e90f2e456e3ccbc4b24e022ce785b1375ff0afbc91cab27b31319c4bf40dab731900d77bced3788d9acb1cdceaec4b9d6483c984c0e8e0d4a20549f598c
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2020 Code and Effect Inc.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Effective Polls
|
|
2
|
+
|
|
3
|
+
Online polls and user voting.
|
|
4
|
+
|
|
5
|
+
An admin creates polls with one or more poll_questions. The poll can be assigned to users through a poll_ballot.
|
|
6
|
+
|
|
7
|
+
The user can complete the poll_ballot and anonymously vote for each option.
|
|
8
|
+
|
|
9
|
+
Some reports to display results.
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
Please first install the [effective_datatables](https://github.com/code-and-effect/effective_datatables) gem.
|
|
14
|
+
|
|
15
|
+
Please download and install [Twitter Bootstrap4](http://getbootstrap.com)
|
|
16
|
+
|
|
17
|
+
Add to your Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'effective_polls'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Run the bundle command to install it:
|
|
24
|
+
|
|
25
|
+
```console
|
|
26
|
+
bundle install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then run the generator:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
rails generate effective_polls:install
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The generator will install an initializer which describes all configuration options and creates a database migration.
|
|
36
|
+
|
|
37
|
+
If you want to tweak the table name (to use something other than the default 'polls'), manually adjust both the configuration file and the migration now.
|
|
38
|
+
|
|
39
|
+
Then migrate the database:
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
rake db:migrate
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Polls
|
|
46
|
+
|
|
47
|
+
TODO
|
|
48
|
+
|
|
49
|
+
## Authorization
|
|
50
|
+
|
|
51
|
+
All authorization checks are handled via the config.authorization_method found in the `app/config/initializers/effective_polls.rb` file.
|
|
52
|
+
|
|
53
|
+
It is intended for flow through to CanCan or Pundit, but neither of those gems are required.
|
|
54
|
+
|
|
55
|
+
This method is called by all controller actions with the appropriate action and resource
|
|
56
|
+
|
|
57
|
+
Action will be one of [:index, :show, :new, :create, :edit, :update, :destroy]
|
|
58
|
+
|
|
59
|
+
Resource will the appropriate Effective::Poll object or class
|
|
60
|
+
|
|
61
|
+
The authorization method is defined in the initializer file:
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
# As a Proc (with CanCan)
|
|
65
|
+
config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
# As a Custom Method
|
|
70
|
+
config.authorization_method = :my_authorization_method
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
and then in your application_controller.rb:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
def my_authorization_method(action, resource)
|
|
77
|
+
current_user.is?(:admin) || EffectivePunditPolicy.new(current_user, resource).send('#{action}?')
|
|
78
|
+
end
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
or disabled entirely:
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
config.authorization_method = false
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
If the method or proc returns false (user is not authorized) an Effective::AccessDenied exception will be raised
|
|
88
|
+
|
|
89
|
+
You can rescue from this exception by adding the following to your application_controller.rb:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
rescue_from Effective::AccessDenied do |exception|
|
|
93
|
+
respond_to do |format|
|
|
94
|
+
format.html { render 'static_pages/access_denied', status: 403 }
|
|
95
|
+
format.any { render text: 'Access Denied', status: 403 }
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
```
|
|
99
|
+
|
|
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
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
|
116
|
+
|
|
117
|
+
## Testing
|
|
118
|
+
|
|
119
|
+
Run tests by:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
rails test
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Contributing
|
|
126
|
+
|
|
127
|
+
1. Fork it
|
|
128
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
129
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
130
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
131
|
+
5. Bonus points for test coverage
|
|
132
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
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
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
load 'rails/tasks/statistics.rake'
|
|
21
|
+
|
|
22
|
+
require 'bundler/gem_tasks'
|
|
23
|
+
|
|
24
|
+
require 'rake/testtask'
|
|
25
|
+
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'test'
|
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
|
29
|
+
t.verbose = false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
task default: :test
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//= link_directory ../stylesheets .css
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class PollNotificationsController < ApplicationController
|
|
3
|
+
layout (EffectivePolls.layout.kind_of?(Hash) ? EffectivePolls.layout[:admin] : EffectivePolls.layout)
|
|
4
|
+
|
|
5
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
6
|
+
before_action { EffectivePolls.authorize!(self, :admin, :effective_polls) }
|
|
7
|
+
|
|
8
|
+
include Effective::CrudController
|
|
9
|
+
|
|
10
|
+
def permitted_params
|
|
11
|
+
params.require(:effective_poll_notification).permit!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class PollQuestionsController < ApplicationController
|
|
3
|
+
layout (EffectivePolls.layout.kind_of?(Hash) ? EffectivePolls.layout[:admin] : EffectivePolls.layout)
|
|
4
|
+
|
|
5
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
6
|
+
before_action { EffectivePolls.authorize!(self, :admin, :effective_polls) }
|
|
7
|
+
|
|
8
|
+
include Effective::CrudController
|
|
9
|
+
|
|
10
|
+
def permitted_params
|
|
11
|
+
params.require(:effective_poll_question).permit!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class PollsController < ApplicationController
|
|
3
|
+
layout (EffectivePolls.layout.kind_of?(Hash) ? EffectivePolls.layout[:admin] : EffectivePolls.layout)
|
|
4
|
+
|
|
5
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
6
|
+
before_action { EffectivePolls.authorize!(self, :admin, :effective_polls) }
|
|
7
|
+
|
|
8
|
+
include Effective::CrudController
|
|
9
|
+
|
|
10
|
+
def results
|
|
11
|
+
@poll = Effective::Poll.find(params[:id])
|
|
12
|
+
EffectivePolls.authorize!(self, :results, @poll)
|
|
13
|
+
|
|
14
|
+
@datatable = Admin::EffectivePollResultsDatatable.new(poll_token: @poll.token)
|
|
15
|
+
@page_title = "#{@poll} Results"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def permitted_params
|
|
19
|
+
params.require(:effective_poll).permit!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class BallotsController < ApplicationController
|
|
3
|
+
layout (EffectivePolls.layout.kind_of?(Hash) ? EffectivePolls.layout[:polls] : EffectivePolls.layout)
|
|
4
|
+
|
|
5
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
6
|
+
include Effective::WizardController
|
|
7
|
+
|
|
8
|
+
resource_scope do
|
|
9
|
+
poll = Effective::Poll.find(params[:poll_id])
|
|
10
|
+
Effective::Ballot.deep.where(poll: poll, user: current_user)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Enforce one ballot per user. Redirect them to an existing ballot for this poll.
|
|
14
|
+
before_action(only: [:new, :show]) do
|
|
15
|
+
poll = Effective::Poll.find(params[:poll_id])
|
|
16
|
+
existing = Effective::Ballot.where(poll: poll, user: current_user).where.not(id: resource).first
|
|
17
|
+
|
|
18
|
+
if existing&.completed?
|
|
19
|
+
flash[:danger] = 'You have already completed a ballot for this poll.'
|
|
20
|
+
redirect_to(root_path)
|
|
21
|
+
elsif existing.present?
|
|
22
|
+
flash[:success] = "You have been redirected to the #{resource_wizard_step_title(existing.next_step)} step."
|
|
23
|
+
redirect_to effective_polls.poll_ballot_build_path(existing.poll, existing, existing.next_step)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Enforce poll availability
|
|
28
|
+
before_action(only: [:show, :update]) do
|
|
29
|
+
poll = resource.poll
|
|
30
|
+
|
|
31
|
+
unless poll.available_for?(current_user)
|
|
32
|
+
flash[:danger] = begin
|
|
33
|
+
if poll.ended?
|
|
34
|
+
'This poll has ended'
|
|
35
|
+
elsif !poll.started?
|
|
36
|
+
'This poll has not yet started'
|
|
37
|
+
elsif !poll.users.include?(current_user)
|
|
38
|
+
'This poll is not available to you'
|
|
39
|
+
else
|
|
40
|
+
'This poll is unavailable'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
redirect_to(root_path)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def permitted_params
|
|
51
|
+
case step
|
|
52
|
+
when :start
|
|
53
|
+
params.require(:effective_ballot).permit(:current_step)
|
|
54
|
+
when :vote
|
|
55
|
+
params.require(:effective_ballot).permit(:current_step, ballot_responses_attributes: [
|
|
56
|
+
:id, :poll_id, :poll_question_id,
|
|
57
|
+
:date, :email, :number, :long_answer, :short_answer, :upload_file,
|
|
58
|
+
:poll_question_option_ids, poll_question_option_ids: []
|
|
59
|
+
])
|
|
60
|
+
when :submit
|
|
61
|
+
params.require(:effective_ballot).permit(:current_step)
|
|
62
|
+
when :complete
|
|
63
|
+
raise('unexpected post to complete')
|
|
64
|
+
else
|
|
65
|
+
raise('unexpected step')
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class PollsController < ApplicationController
|
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
4
|
+
|
|
5
|
+
def show
|
|
6
|
+
poll = Effective::Poll.find(params[:id])
|
|
7
|
+
EffectivePolls.authorize!(self, :show, poll)
|
|
8
|
+
|
|
9
|
+
ballot = Effective::Ballot.where(poll: poll, user: current_user).first
|
|
10
|
+
|
|
11
|
+
if ballot.present?
|
|
12
|
+
redirect_to effective_polls.poll_ballot_build_path(poll, ballot, ballot.next_step)
|
|
13
|
+
else
|
|
14
|
+
redirect_to effective_polls.poll_ballot_build_path(poll, :new, :start)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class Admin::EffectivePollNotificationsDatatable < Effective::Datatable
|
|
2
|
+
filters do
|
|
3
|
+
scope :all
|
|
4
|
+
scope :started
|
|
5
|
+
scope :completed
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
datatable do
|
|
9
|
+
col :updated_at, visible: false
|
|
10
|
+
col :created_at, visible: false
|
|
11
|
+
col :id, visible: false
|
|
12
|
+
|
|
13
|
+
col :poll
|
|
14
|
+
col :category
|
|
15
|
+
|
|
16
|
+
col :reminder do |poll_notification|
|
|
17
|
+
case poll_notification.category
|
|
18
|
+
when 'When poll starts'
|
|
19
|
+
poll_notification.poll.start_at&.strftime('%F %H:%M')
|
|
20
|
+
when 'When poll ends'
|
|
21
|
+
poll_notification.poll.end_at&.strftime('%F %H:%M')
|
|
22
|
+
when 'Upcoming reminder'
|
|
23
|
+
Effective::PollNotification::UPCOMING_REMINDERS.invert[poll_notification.reminder]
|
|
24
|
+
when 'Reminder'
|
|
25
|
+
Effective::PollNotification::REMINDERS.invert[poll_notification.reminder]
|
|
26
|
+
else
|
|
27
|
+
raise('unexpected category')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
col :subject
|
|
32
|
+
col :body
|
|
33
|
+
|
|
34
|
+
col :started_at, visible: false
|
|
35
|
+
col :completed_at
|
|
36
|
+
|
|
37
|
+
actions_col
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
collection do
|
|
41
|
+
Effective::PollNotification.all.deep
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Admin::EffectivePollQuestionsDatatable < Effective::Datatable
|
|
2
|
+
datatable do
|
|
3
|
+
reorder :position
|
|
4
|
+
|
|
5
|
+
col :updated_at, visible: false
|
|
6
|
+
col :created_at, visible: false
|
|
7
|
+
col :id, visible: false
|
|
8
|
+
|
|
9
|
+
col :poll
|
|
10
|
+
|
|
11
|
+
col :position do |poll_question|
|
|
12
|
+
poll_question.position.to_i + 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
col :title
|
|
16
|
+
col :body
|
|
17
|
+
col :required
|
|
18
|
+
|
|
19
|
+
col :category, label: 'Type'
|
|
20
|
+
col :poll_question_options, label: 'Options'
|
|
21
|
+
|
|
22
|
+
actions_col
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
collection do
|
|
26
|
+
Effective::PollQuestion.all.deep
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class Admin::EffectivePollResultsDatatable < Effective::Datatable
|
|
2
|
+
datatable do
|
|
3
|
+
col :ballot, search: poll.completed_ballots.order(:token).pluck(:token)
|
|
4
|
+
|
|
5
|
+
col :position, visible: false
|
|
6
|
+
col :category, search: Effective::PollQuestion::CATEGORIES, visible: false
|
|
7
|
+
|
|
8
|
+
col :question, search: poll.poll_questions.pluck(:title)
|
|
9
|
+
col :responses
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
collection do
|
|
13
|
+
ballot_responses = Effective::BallotResponse.completed.deep.where(poll: poll)
|
|
14
|
+
|
|
15
|
+
ballot_responses.flat_map do |br|
|
|
16
|
+
rows = if br.poll_question.poll_question_option?
|
|
17
|
+
br.poll_question_options.map do |response|
|
|
18
|
+
[
|
|
19
|
+
br.ballot.token,
|
|
20
|
+
br.poll_question.position,
|
|
21
|
+
br.poll_question.category,
|
|
22
|
+
br.poll_question.to_s,
|
|
23
|
+
response.to_s
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
elsif br.response.present?
|
|
27
|
+
[
|
|
28
|
+
[
|
|
29
|
+
br.ballot.token,
|
|
30
|
+
br.poll_question.position,
|
|
31
|
+
br.poll_question.category,
|
|
32
|
+
br.poll_question.to_s,
|
|
33
|
+
br.response.to_s
|
|
34
|
+
]
|
|
35
|
+
]
|
|
36
|
+
else
|
|
37
|
+
[]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
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
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|