effective_committees 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +186 -0
- data/Rakefile +18 -0
- data/app/assets/config/effective_committees_manifest.js +3 -0
- data/app/assets/javascripts/effective_committees/base.js +0 -0
- data/app/assets/javascripts/effective_committeesjs +1 -0
- data/app/assets/stylesheets/effective_committees/base.scss +0 -0
- data/app/assets/stylesheets/effective_committees.scss +1 -0
- data/app/controllers/admin/committee_files_controller.rb +16 -0
- data/app/controllers/admin/committee_folders_controller.rb +16 -0
- data/app/controllers/admin/committee_members_controller.rb +16 -0
- data/app/controllers/admin/committees_controller.rb +22 -0
- data/app/controllers/effective/committee_folders_controller.rb +7 -0
- data/app/controllers/effective/committee_members_controller.rb +19 -0
- data/app/controllers/effective/committees_controller.rb +17 -0
- data/app/datatables/admin/effective_committee_files_datatable.rb +24 -0
- data/app/datatables/admin/effective_committee_folders_datatable.rb +28 -0
- data/app/datatables/admin/effective_committee_members_datatable.rb +32 -0
- data/app/datatables/admin/effective_committees_datatable.rb +34 -0
- data/app/datatables/effective_committee_members_datatable.rb +42 -0
- data/app/datatables/effective_committees_datatable.rb +31 -0
- data/app/helpers/effective_committees_helper.rb +3 -0
- data/app/models/concerns/effective_committees_user.rb +40 -0
- data/app/models/effective/committee.rb +55 -0
- data/app/models/effective/committee_file.rb +40 -0
- data/app/models/effective/committee_folder.rb +42 -0
- data/app/models/effective/committee_member.rb +76 -0
- data/app/views/admin/committee_files/_form.html.haml +14 -0
- data/app/views/admin/committee_folders/_form.html.haml +21 -0
- data/app/views/admin/committee_members/_form.html.haml +31 -0
- data/app/views/admin/committee_members/_user_fields.html.haml +7 -0
- data/app/views/admin/committees/_fields.html.haml +7 -0
- data/app/views/admin/committees/_form.html.haml +20 -0
- data/app/views/admin/committees/_form_committee.html.haml +6 -0
- data/app/views/effective/committee_folders/_committee_folder.html.haml +24 -0
- data/app/views/effective/committee_members/_form.html.haml +35 -0
- data/app/views/effective/committee_members/_user_fields.html.haml +7 -0
- data/app/views/effective/committees/_committee.html.haml +23 -0
- data/app/views/effective/committees/_dashboard.html.haml +10 -0
- data/app/views/effective/committees/_fields.html.haml +2 -0
- data/app/views/effective/committees/_form.html.haml +8 -0
- data/app/views/effective/committees/_form_committee.html.haml +11 -0
- data/app/views/effective/committees/index.html.haml +21 -0
- data/config/effective_committees.rb +13 -0
- data/config/routes.rb +24 -0
- data/db/migrate/01_create_effective_committees.rb.erb +14 -0
- data/db/seeds.rb +1 -0
- data/lib/effective_committees/engine.rb +18 -0
- data/lib/effective_committees/version.rb +3 -0
- data/lib/effective_committees.rb +18 -0
- data/lib/generators/effective_committees/install_generator.rb +31 -0
- data/lib/generators/templates/effective_committees_mailer_preview.rb +4 -0
- data/lib/tasks/effective_committees_tasks.rake +8 -0
- metadata +250 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b793fe3d40958ea8fc7e853979a10ef40cdbdfc043893b93690ad62f8d5c7604
|
4
|
+
data.tar.gz: 414192d935ae2fc8f6b5b24617a97c219e72a069728c8e3a22241ef7449301bb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 784a0ccd91b3d7fdff1023a75f41506a771b17293ad73cb4c14de8d1184cd1c580a10c46d29072302c182ed906d13910f6837e191169306e052fbf77b30a5a74
|
7
|
+
data.tar.gz: 0b09e1874e3a24d4e29b71e12ecddf4920634d4c57fcdbf0a1c5d6e49210fb5e5b18c80d9d4507d0fbec1bd8852f19b18d4c13a0befe7530c0e6924c4d5d7495
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 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,186 @@
|
|
1
|
+
# Effective Committees
|
2
|
+
|
3
|
+
Committees are groups of users that can all share files.
|
4
|
+
|
5
|
+
## Getting Started
|
6
|
+
|
7
|
+
This requires Rails 6+ and Twitter Bootstrap 4 and just works with Devise.
|
8
|
+
|
9
|
+
Please first install the [effective_datatables](https://github.com/code-and-effect/effective_datatables) gem.
|
10
|
+
|
11
|
+
Please download and install the [Twitter Bootstrap4](http://getbootstrap.com)
|
12
|
+
|
13
|
+
Add to your Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'haml-rails' # or try using gem 'hamlit-rails'
|
17
|
+
gem 'effective_committees'
|
18
|
+
```
|
19
|
+
|
20
|
+
Run the bundle command to install it:
|
21
|
+
|
22
|
+
```console
|
23
|
+
bundle install
|
24
|
+
```
|
25
|
+
|
26
|
+
Then run the generator:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
rails generate effective_committees:install
|
30
|
+
```
|
31
|
+
|
32
|
+
The generator will install an initializer which describes all configuration options and creates a database migration.
|
33
|
+
|
34
|
+
If you want to tweak the table names, manually adjust both the configuration file and the migration now.
|
35
|
+
|
36
|
+
Then migrate the database:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
rake db:migrate
|
40
|
+
```
|
41
|
+
|
42
|
+
Please add the following to your User model:
|
43
|
+
|
44
|
+
```
|
45
|
+
effective_committees_user
|
46
|
+
|
47
|
+
Use the following datatables to display to your user their applicants dues:
|
48
|
+
|
49
|
+
```haml
|
50
|
+
%h2 My Committees
|
51
|
+
= render 'effective/committees/dashboard'
|
52
|
+
```
|
53
|
+
|
54
|
+
and
|
55
|
+
|
56
|
+
```
|
57
|
+
Add a link to the admin menu:
|
58
|
+
|
59
|
+
```haml
|
60
|
+
- if can? :admin, :effective_committees
|
61
|
+
= nav_dropdown 'Committees' do
|
62
|
+
- if can? :index, Effective::Committee
|
63
|
+
= nav_link_to 'Committees', effective_committees.admin_committees_path
|
64
|
+
|
65
|
+
- if can? :index, Effective::CommitteeMember
|
66
|
+
= nav_link_to 'Committee Members', effective_committees.admin_committee_members_path
|
67
|
+
|
68
|
+
- if can? :index, Effective::CommitteeFolder
|
69
|
+
= nav_link_to 'Committee Folders', effective_committees.admin_committee_folders_path
|
70
|
+
|
71
|
+
- if can? :index, Effective::CommitteeFile
|
72
|
+
= nav_link_to 'Committee Files', effective_committees.admin_committee_files_path
|
73
|
+
```
|
74
|
+
|
75
|
+
## Configuration
|
76
|
+
|
77
|
+
## Authorization
|
78
|
+
|
79
|
+
All authorization checks are handled via the effective_resources gem found in the `config/initializers/effective_resources.rb` file.
|
80
|
+
|
81
|
+
## Effective Roles
|
82
|
+
|
83
|
+
This gem works with effective roles for the representative roles.
|
84
|
+
|
85
|
+
Configure your `config/initializers/effective_roles.rb` something like this:
|
86
|
+
|
87
|
+
```
|
88
|
+
EffectiveRoles.setup do |config|
|
89
|
+
config.roles = [:admin, :reserved, :owner, :billing] # Only add to the end of this array. Never prepend roles.
|
90
|
+
|
91
|
+
# config.role_descriptions
|
92
|
+
# ========================
|
93
|
+
# This setting configures the text that is displayed by form helpers (see README.md)
|
94
|
+
|
95
|
+
config.role_descriptions = {
|
96
|
+
'User' => {
|
97
|
+
# User roles
|
98
|
+
admin: 'can log in to the /admin section of the website. full access to everything.',
|
99
|
+
},
|
100
|
+
'Effective::CommitteeMember' => {
|
101
|
+
owner: 'committee owner. full access to everything.',
|
102
|
+
billing: 'the billing contact. full access to everything.'
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
# config.assignable_roles
|
107
|
+
# Which roles can be assigned by whom
|
108
|
+
# =======================
|
109
|
+
# When current_user is passed into a form helper function (see README.md)
|
110
|
+
# this setting determines which roles that current_user may assign
|
111
|
+
config.assignable_roles = {
|
112
|
+
'User' => { admin: [:admin] },
|
113
|
+
|
114
|
+
'Effective::CommitteeMember' => {
|
115
|
+
admin: [:owner, :billing],
|
116
|
+
owner: [:owner, :billing],
|
117
|
+
billing: [:billing]
|
118
|
+
}
|
119
|
+
}
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
## Permissions
|
124
|
+
|
125
|
+
The permissions you actually want to define are as follows (using CanCan):
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
if user.persisted?
|
129
|
+
can :index, Effective::Committee
|
130
|
+
can(:show, Effective::Committee) { |committee| user.committees.include?(committee) }
|
131
|
+
|
132
|
+
can([:edit, :update], Effective::Committee) do |committee|
|
133
|
+
user.committee_member(committee: committee)&.is?(:owner)
|
134
|
+
end
|
135
|
+
|
136
|
+
can :index, Effective::CommitteeMember
|
137
|
+
|
138
|
+
can(:show, Effective::CommitteeMember) { |member| user.committees.include?(member.committee) }
|
139
|
+
can(:new, Effective::CommitteeMember)
|
140
|
+
|
141
|
+
can([:create, :edit, :update], Effective::CommitteeMember) do |cm|
|
142
|
+
user.committee_member(committee: cm.committee)&.is?(:owner)
|
143
|
+
end
|
144
|
+
|
145
|
+
can(:destroy, Effective::CommitteeMember) do |member|
|
146
|
+
user.committee_member(committee: member.committee)&.is?(:owner) && !member.is?(:owner)
|
147
|
+
end
|
148
|
+
|
149
|
+
can(:show, Effective::CommitteeFolder) { |folder| user.committees.include?(folder.committee) }
|
150
|
+
can(:show, Effective::CommitteeFile) { |file| user.committees.include?(file.committee) }
|
151
|
+
end
|
152
|
+
|
153
|
+
if user.admin?
|
154
|
+
can :admin, :effective_committees
|
155
|
+
|
156
|
+
can(crud - [:destroy], Effective::Committee)
|
157
|
+
can(:destroy, Effective::Committee) { |committee| committee.committee_members_count == 0 }
|
158
|
+
|
159
|
+
can(crud - [:destroy], Effective::CommitteeFolder)
|
160
|
+
can(:destroy, Effective::CommitteeFolder) { |folder| folder.committee_files_count == 0 }
|
161
|
+
|
162
|
+
can(crud, Effective::CommitteeMember)
|
163
|
+
can(crud, Effective::CommitteeFile)
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
## License
|
168
|
+
|
169
|
+
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
170
|
+
|
171
|
+
## Testing
|
172
|
+
|
173
|
+
Run tests by:
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
rails test
|
177
|
+
```
|
178
|
+
|
179
|
+
## Contributing
|
180
|
+
|
181
|
+
1. Fork it
|
182
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
183
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
184
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
185
|
+
5. Bonus points for test coverage
|
186
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
|
+
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
require "bundler/gem_tasks"
|
9
|
+
|
10
|
+
require "rake/testtask"
|
11
|
+
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: :test
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree ./effective_committees
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
@import 'effective_committees/base';
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Admin
|
2
|
+
class CommitteeFilesController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_committees) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def permitted_params
|
11
|
+
model = (params.key?(:effective_committee_file) ? :effective_committee_file : :committee_file)
|
12
|
+
params.require(model).permit!
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Admin
|
2
|
+
class CommitteeFoldersController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_committees) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def permitted_params
|
11
|
+
model = (params.key?(:effective_committee_folder) ? :effective_committee_folder : :committee_folder)
|
12
|
+
params.require(model).permit!
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Admin
|
2
|
+
class CommitteeMembersController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_committees) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def permitted_params
|
11
|
+
model = (params.key?(:effective_committee_member) ? :effective_committee_member : :committee_member)
|
12
|
+
params.require(model).permit!
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Admin
|
2
|
+
class CommitteesController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_committees) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
submit :save, 'Save'
|
9
|
+
submit :save, 'Save and Add New', redirect: :new
|
10
|
+
submit :save, 'Save and View', redirect: -> { effective_committees.committee_path(resource) }
|
11
|
+
|
12
|
+
resource_scope -> { Effective::Committee.deep.all }
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def permitted_params
|
17
|
+
model = (params.key?(:effective_committee) ? :effective_committee : :committee)
|
18
|
+
params.require(model).permit!
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Effective
|
2
|
+
class CommitteeMembersController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
|
5
|
+
include Effective::CrudController
|
6
|
+
|
7
|
+
resource_scope -> {
|
8
|
+
committees = Effective::Committee.deep.where(id: current_user.committees)
|
9
|
+
Effective::CommitteeMember.deep.where(committee: committees)
|
10
|
+
}
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def permitted_params
|
15
|
+
params.require(:effective_committee_member).permit!
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Effective
|
2
|
+
class CommitteesController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
|
5
|
+
include Effective::CrudController
|
6
|
+
|
7
|
+
resource_scope -> { Effective::Committee.all.deep }
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def permitted_params
|
12
|
+
model = (params.key?(:effective_committee) ? :effective_committee : :committee)
|
13
|
+
params.require(model).permit!
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveCommitteeFilesDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
col :updated_at, visible: false
|
5
|
+
col :created_at, visible: false
|
6
|
+
|
7
|
+
col :id, visible: false
|
8
|
+
|
9
|
+
col :committee, search: :string
|
10
|
+
col :committee_folder, search: :string, label: 'Folder'
|
11
|
+
|
12
|
+
col :file
|
13
|
+
col :title
|
14
|
+
col :notes
|
15
|
+
|
16
|
+
actions_col
|
17
|
+
end
|
18
|
+
|
19
|
+
collection do
|
20
|
+
Effective::CommitteeFile.deep.all
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveCommitteeFoldersDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
reorder :position
|
5
|
+
|
6
|
+
col :updated_at, visible: false
|
7
|
+
col :created_at, visible: false
|
8
|
+
|
9
|
+
col :id, visible: false
|
10
|
+
|
11
|
+
col :committee, search: :string
|
12
|
+
|
13
|
+
col :title, label: 'Folder'
|
14
|
+
col :slug, visible: false
|
15
|
+
col :body
|
16
|
+
|
17
|
+
col :committee_files, label: 'Files', search: :string
|
18
|
+
col :committee_files_count, label: 'Files Count', visible: false
|
19
|
+
|
20
|
+
actions_col
|
21
|
+
end
|
22
|
+
|
23
|
+
collection do
|
24
|
+
Effective::CommitteeFolder.deep.all
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveCommitteeMembersDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
col :id, visible: false
|
5
|
+
col :user_id, visible: false
|
6
|
+
|
7
|
+
col :committee
|
8
|
+
col :user
|
9
|
+
|
10
|
+
unless attributes[:user_id]
|
11
|
+
col :email do |committee_member|
|
12
|
+
mail_to(committee_member.user.email)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if EffectiveCommittees.use_effective_roles
|
17
|
+
col :roles, search: roles_collection
|
18
|
+
end
|
19
|
+
|
20
|
+
actions_col
|
21
|
+
end
|
22
|
+
|
23
|
+
collection do
|
24
|
+
Effective::CommitteeMember.deep.all
|
25
|
+
end
|
26
|
+
|
27
|
+
def roles_collection
|
28
|
+
EffectiveRoles.roles_collection(Effective::CommitteeMember.new).map(&:second)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveCommitteesDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
|
5
|
+
col :updated_at, visible: false
|
6
|
+
col :created_at, visible: false
|
7
|
+
|
8
|
+
col :id, visible: false
|
9
|
+
|
10
|
+
col :title, label: 'Committee'
|
11
|
+
col :slug, visible: false
|
12
|
+
col :body
|
13
|
+
|
14
|
+
col :committee_members, label: 'Members', search: :string
|
15
|
+
col :committee_members_count, label: 'Members Count', visible: false
|
16
|
+
|
17
|
+
col :committee_folders, label: 'Folders', search: :string
|
18
|
+
col :committee_folders_count, label: 'Folders Count', visible: false
|
19
|
+
|
20
|
+
col :committee_files, label: 'Files', search: :string
|
21
|
+
col :committee_files_count, label: 'Files Count', visible: false
|
22
|
+
|
23
|
+
actions_col do |committee|
|
24
|
+
dropdown_link_to('View Committee', effective_committees.committee_path(committee), target: '_blank')
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
collection do
|
30
|
+
Effective::Committee.deep.all
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class EffectiveCommitteeMembersDatatable < Effective::Datatable
|
2
|
+
datatable do
|
3
|
+
col :id, visible: false
|
4
|
+
|
5
|
+
col :committee
|
6
|
+
col :user
|
7
|
+
|
8
|
+
unless attributes[:user_id]
|
9
|
+
col :email do |committee_member|
|
10
|
+
mail_to(committee_member.user.email)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if EffectiveCommittees.use_effective_roles
|
15
|
+
col :roles, search: roles_collection
|
16
|
+
end
|
17
|
+
|
18
|
+
unless attributes[:actions] == false
|
19
|
+
actions_col
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
collection do
|
25
|
+
scope = Effective::CommitteeMember.deep.all.where(committee: current_user.committees)
|
26
|
+
|
27
|
+
if attributes[:committee_id]
|
28
|
+
scope = scope.where(committee_id: attributes[:committee_id])
|
29
|
+
end
|
30
|
+
|
31
|
+
if attributes[:user_id]
|
32
|
+
scope = scope.where(user_id: attributes[:user_id])
|
33
|
+
end
|
34
|
+
|
35
|
+
scope
|
36
|
+
end
|
37
|
+
|
38
|
+
def roles_collection
|
39
|
+
EffectiveRoles.roles_collection(Effective::CommitteeMember.new).map(&:second)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Dashboard Committees
|
2
|
+
class EffectiveCommitteesDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
order :title
|
5
|
+
|
6
|
+
col :id, visible: false
|
7
|
+
|
8
|
+
col :title, label: 'Committee'
|
9
|
+
|
10
|
+
col :committee_members, search: :string, label: 'Members'
|
11
|
+
|
12
|
+
col :committee_folders, search: :string, label: 'Folders'
|
13
|
+
|
14
|
+
col :committee_folders_count, label: 'Folders', visible: false do |committee|
|
15
|
+
pluralize(committee.committee_folders_count, 'folders')
|
16
|
+
end
|
17
|
+
|
18
|
+
col :committee_files, search: :string, label: 'Files', visible: false
|
19
|
+
|
20
|
+
col :committee_files_count, label: 'Files' do |committee|
|
21
|
+
pluralize(committee.committee_files_count, 'files')
|
22
|
+
end
|
23
|
+
|
24
|
+
actions_col
|
25
|
+
end
|
26
|
+
|
27
|
+
collection do
|
28
|
+
Effective::Committee.deep.where(id: current_user.committees)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# EffectiveCommitteesUser
|
2
|
+
#
|
3
|
+
# Mark your user model with effective_committees_user to get all the includes
|
4
|
+
|
5
|
+
module EffectiveCommitteesUser
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module Base
|
9
|
+
def effective_committees_user
|
10
|
+
include ::EffectiveCommitteesUser
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def effective_committees_user?; true; end
|
16
|
+
end
|
17
|
+
|
18
|
+
included do
|
19
|
+
has_many :committee_members, -> { Effective::CommitteeMember.sorted },
|
20
|
+
class_name: 'Effective::CommitteeMember', inverse_of: :user, dependent: :delete_all
|
21
|
+
|
22
|
+
accepts_nested_attributes_for :committee_members, allow_destroy: true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Instance Methods
|
26
|
+
|
27
|
+
def committee_member(committee:)
|
28
|
+
committee_members.find { |rep| rep.committee_id == committee.id }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Find or build
|
32
|
+
def build_committee_member(committee:)
|
33
|
+
committee_member(committee: committee) || committee_members.build(committee: committee)
|
34
|
+
end
|
35
|
+
|
36
|
+
def committees
|
37
|
+
committee_members.reject(&:marked_for_destruction?).map(&:committee)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class Committee < ActiveRecord::Base
|
5
|
+
self.table_name = EffectiveCommittees.committees_table_name.to_s
|
6
|
+
|
7
|
+
acts_as_slugged
|
8
|
+
|
9
|
+
log_changes if respond_to?(:log_changes)
|
10
|
+
has_rich_text :body
|
11
|
+
|
12
|
+
has_many :committee_members, -> { Effective::CommitteeMember.sorted }, class_name: 'Effective::CommitteeMember', inverse_of: :committee, dependent: :delete_all
|
13
|
+
accepts_nested_attributes_for :committee_members, allow_destroy: true
|
14
|
+
|
15
|
+
has_many :committee_folders, -> { Effective::CommitteeFolder.sorted }, class_name: 'Effective::CommitteeFolder', inverse_of: :committee, dependent: :delete_all
|
16
|
+
accepts_nested_attributes_for :committee_folders, allow_destroy: true
|
17
|
+
|
18
|
+
has_many :committee_files, -> { Effective::CommitteeFile.sorted }, class_name: 'Effective::CommitteeFile', inverse_of: :committee, dependent: :delete_all
|
19
|
+
accepts_nested_attributes_for :committee_files, allow_destroy: true
|
20
|
+
|
21
|
+
effective_resource do
|
22
|
+
title :string
|
23
|
+
slug :string
|
24
|
+
|
25
|
+
committee_members_count :integer # Counter Cache
|
26
|
+
committee_folders_count :integer # Counter Cache
|
27
|
+
committee_files_count :integer # Counter Cache
|
28
|
+
|
29
|
+
timestamps
|
30
|
+
end
|
31
|
+
|
32
|
+
scope :sorted, -> { order(:title) }
|
33
|
+
scope :deep, -> { includes(:committee_members) }
|
34
|
+
|
35
|
+
validates :title, presence: true, uniqueness: true, length: { maximum: 255 }
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
title.presence || 'New Committee'
|
39
|
+
end
|
40
|
+
|
41
|
+
def committee_member(user:)
|
42
|
+
committee_members.find { |member| member.user_id == user.id }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Find or build
|
46
|
+
def build_committee_member(user:)
|
47
|
+
committee_member(user: user) || committee_members.build(user: user)
|
48
|
+
end
|
49
|
+
|
50
|
+
def users
|
51
|
+
committee_members.reject(&:marked_for_destruction?).map(&:user)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|