effective_committees 0.4.3 → 0.5.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.
- checksums.yaml +4 -4
- data/app/controllers/effective/committees_controller.rb +5 -0
- data/app/datatables/admin/effective_committee_members_datatable.rb +6 -2
- data/app/datatables/effective_committees_activity_datatable.rb +42 -0
- data/app/datatables/effective_committees_datatable.rb +1 -1
- data/app/models/concerns/effective_committees_user.rb +24 -0
- data/app/models/effective/committee_file.rb +4 -1
- data/app/views/effective/committee_folders/_committee_folder.html.haml +1 -1
- data/app/views/effective/committee_folders/show.html.haml +13 -0
- data/app/views/effective/committees/_committee.html.haml +1 -1
- data/app/views/effective/committees/_dashboard.html.haml +1 -1
- data/app/views/effective/committees/_dashboard_activity.html.haml +30 -0
- data/app/views/effective/committees/activity.html.haml +19 -0
- data/app/views/effective/committees/my_committees.html.haml +1 -1
- data/app/views/effective/committees/show.html.haml +13 -0
- data/config/routes.rb +3 -0
- data/db/migrate/101_create_effective_committees.rb +3 -0
- data/lib/effective_committees/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2a318a62bd5057b979e35eb0280f7db899f83367a80726e13471444bd80d758
|
4
|
+
data.tar.gz: 01d660c74f301d9a82627cf7d15782db30bac3bee2e717720fd1d54b77bdd3fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f07fb6ef7c974f646a35186845541752b522a286657efe3158eb99262244274efc09d610d7799218c0a92931cab86394946dd83f5b1ba91a7b3bad4cea43b40d
|
7
|
+
data.tar.gz: dfa60d6d7d0926ec9ada024243139fce61088251bff4da53b8a69a94b6db46207535f8ab9c785c46f992d1f346b387b96f6b89ced4697d6805199f23263f42d3
|
@@ -6,16 +6,21 @@ module Effective
|
|
6
6
|
log_page_views(if: -> { EffectiveCommittees.log_page_views? })
|
7
7
|
|
8
8
|
resource_scope -> { Effective::Committee.all.deep }
|
9
|
+
page_title "More Activity", only: [:activity]
|
9
10
|
|
10
11
|
def index
|
11
12
|
@committees = resource_scope.for_index
|
12
13
|
@page_title = EffectiveResources.et('effective_committees.name')
|
13
14
|
|
14
15
|
EffectiveResources.authorize!(self, :index, Effective::Committee)
|
16
|
+
EffectiveResources.authorize!(self, :all_committees, Effective::Committee)
|
15
17
|
|
16
18
|
render 'index'
|
17
19
|
end
|
18
20
|
|
21
|
+
# activity
|
22
|
+
# my_committees
|
23
|
+
|
19
24
|
private
|
20
25
|
|
21
26
|
def permitted_params
|
@@ -7,7 +7,7 @@ module Admin
|
|
7
7
|
col :committee
|
8
8
|
col :user
|
9
9
|
|
10
|
-
if
|
10
|
+
if current_user.class.try(:effective_memberships_owner?)
|
11
11
|
col(:member_number, label: 'Member #', sort: false) do |committee_member|
|
12
12
|
committee_member.user.try(:membership).try(:number)
|
13
13
|
end.search do |collection, term|
|
@@ -34,7 +34,11 @@ module Admin
|
|
34
34
|
col :roles, search: roles_collection
|
35
35
|
end
|
36
36
|
|
37
|
-
actions_col
|
37
|
+
actions_col do |committee_member|
|
38
|
+
if EffectiveResources.authorized?(self, :impersonate, committee_member.user)
|
39
|
+
dropdown_link_to("Impersonate", "/admin/users/#{committee_member.user_id}/impersonate", data: { confirm: "Really impersonate #{committee_member.user}?", method: :post, remote: true })
|
40
|
+
end
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
collection do
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# For the /committees/activity More Activity page
|
2
|
+
# Displays all the logged changes for this user's committees
|
3
|
+
class EffectiveCommitteesActivityDatatable < Effective::Datatable
|
4
|
+
datatable do
|
5
|
+
order :id, :desc
|
6
|
+
|
7
|
+
col :updated_at, label: 'Date'
|
8
|
+
col :id, visible: false
|
9
|
+
|
10
|
+
col :user, label: 'Changed by', search: :string, sort: false
|
11
|
+
col :changes_to, label: committee_label, search: current_user.committees
|
12
|
+
col :associated, visible: false
|
13
|
+
|
14
|
+
col :message, sort: false do |log|
|
15
|
+
message = (log.message || '').gsub("\n", '<br>')
|
16
|
+
associated_type = log.associated_type.gsub('Effective::', '').gsub('ActiveStorage::', '')
|
17
|
+
|
18
|
+
if log.associated_id == attributes[:changes_to_id] && log.associated_type == attributes[:changes_to_type]
|
19
|
+
message
|
20
|
+
else
|
21
|
+
"#{associated_type} #{log.associated_to_s} - #{message}"
|
22
|
+
end
|
23
|
+
|
24
|
+
end.search do |collection, term, column, sql_column|
|
25
|
+
ilike = effective_resource.ilike
|
26
|
+
collection.where("associated_type #{ilike} ? OR associated_to_s #{ilike} ? OR message #{ilike} ?", "%#{term}%", "%#{term}%", "%#{term}%")
|
27
|
+
end
|
28
|
+
|
29
|
+
col :details, visible: false, sort: false do |log|
|
30
|
+
tableize_hash(log.details)
|
31
|
+
end
|
32
|
+
|
33
|
+
actions_col
|
34
|
+
end
|
35
|
+
|
36
|
+
collection do
|
37
|
+
EffectiveLogging.Log.logged_changes.deep
|
38
|
+
.where(changes_to_type: 'Effective::Committee', changes_to_id: current_user.committees.map(&:id))
|
39
|
+
.where.not(associated_type: 'ActiveStorage::Attachment')
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -10,7 +10,7 @@ class EffectiveCommitteesDatatable < Effective::Datatable
|
|
10
10
|
col(:committee_members, label: committee_members_label, visible: false) do |committee|
|
11
11
|
committee.committee_members.select(&:active?).sort_by(&:to_s).map do |member|
|
12
12
|
content_tag(:div, class: 'col-resource_item') do
|
13
|
-
label =
|
13
|
+
label = member.to_s
|
14
14
|
badge = badge(member.category) if member.category.present?
|
15
15
|
|
16
16
|
[label, badge].compact.join(' ').html_safe
|
@@ -45,4 +45,28 @@ module EffectiveCommitteesUser
|
|
45
45
|
committee_members.select { |cm| cm.active? && !cm.marked_for_destruction? }.map { |cm| cm.committee }
|
46
46
|
end
|
47
47
|
|
48
|
+
# When activity is for sequential uploaded files, group them together like: "12 files were added to Board of Directors - April 2025 Meeting"
|
49
|
+
def committees_recent_activity(limit: 100)
|
50
|
+
logs = EffectiveLogging.Log.logged_changes.deep
|
51
|
+
.where(changes_to_type: 'Effective::Committee', changes_to_id: committees.map(&:id))
|
52
|
+
.order(created_at: :desc)
|
53
|
+
|
54
|
+
# Recent activity should be for folders being created and files being uploaded/replaced
|
55
|
+
logs = logs.select do |log|
|
56
|
+
folder_created = (log.associated_type == 'Effective::CommitteeFolder' && log.message == 'Created')
|
57
|
+
file_changed = (log.associated_type == 'Effective::CommitteeFile' && (log.message == 'Created' || log.details.dig(:changes, 'File').present?))
|
58
|
+
folder_created || file_changed
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns an Array of Arrays where some are 1 length groups
|
62
|
+
# Others are multiple length groups of file changes to one folder
|
63
|
+
logs = logs.slice_when do |a, b|
|
64
|
+
(a.changes_to_id != b.changes_to_id) ||
|
65
|
+
(a.associated_type != b.associated_type) ||
|
66
|
+
(b.associated_type == "Effective::CommitteeFolder") ||
|
67
|
+
(a.associated.try(:committee_folder_id) != b.associated.try(:committee_folder_id))
|
68
|
+
end
|
69
|
+
|
70
|
+
logs.take(limit)
|
71
|
+
end
|
48
72
|
end
|
@@ -15,6 +15,9 @@ module Effective
|
|
15
15
|
title :string
|
16
16
|
notes :text
|
17
17
|
|
18
|
+
file_id :integer
|
19
|
+
file_created_at :datetime
|
20
|
+
|
18
21
|
timestamps
|
19
22
|
end
|
20
23
|
|
@@ -23,7 +26,7 @@ module Effective
|
|
23
26
|
end
|
24
27
|
|
25
28
|
before_validation(if: -> { file.attached? }) do
|
26
|
-
|
29
|
+
assign_attributes(title: file.filename.to_s, file_id: file.attachment.blob.id, file_created_at: file.attachment.blob.created_at)
|
27
30
|
end
|
28
31
|
|
29
32
|
scope :deep, -> { with_attached_file.includes(:committee, :committee_folder) }
|
@@ -1,7 +1,7 @@
|
|
1
1
|
= render('layout') do
|
2
2
|
%nav{'aria-label': 'breadcrumb'}
|
3
3
|
%ol.breadcrumb
|
4
|
-
- if EffectiveResources.authorized?(self, :
|
4
|
+
- if EffectiveResources.authorized?(self, :all_committees, Effective::Committee)
|
5
5
|
%li.breadcrumb-item= link_to("All #{committees_label}", effective_committees.committees_path)
|
6
6
|
- elsif EffectiveResources.authorized?(self, :my_committees, Effective::Committee)
|
7
7
|
%li.breadcrumb-item= link_to("My #{committees_label}", effective_committees.my_committees_path)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
- resource = (@_effective_resource || Effective::Resource.new(controller_path))
|
2
|
+
- @resource = instance_variable_get('@' + resource.name) if resource.name
|
3
|
+
|
4
|
+
- if @resource
|
5
|
+
.resource-buttons
|
6
|
+
= render_resource_buttons(@resource, show: false)
|
7
|
+
|
8
|
+
= render_resource_partial(@resource)
|
9
|
+
|
10
|
+
.my-4
|
11
|
+
|
12
|
+
-# .form-actions
|
13
|
+
-# = link_to 'Continue', return_to_dashboard_path, class: 'btn btn-primary mb-4'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
= render('layout') do
|
2
2
|
%nav{'aria-label': 'breadcrumb'}
|
3
3
|
%ol.breadcrumb
|
4
|
-
- if EffectiveResources.authorized?(self, :
|
4
|
+
- if EffectiveResources.authorized?(self, :all_committees, Effective::Committee)
|
5
5
|
%li.breadcrumb-item= link_to("All #{committees_label}", effective_committees.committees_path)
|
6
6
|
- elsif EffectiveResources.authorized?(self, :my_committees, Effective::Committee)
|
7
7
|
%li.breadcrumb-item= link_to("My #{committees_label}", effective_committees.my_committees_path)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
%p
|
5
5
|
You have access to #{pluralize(current_user.committees.length, committee_label.downcase)}.
|
6
6
|
|
7
|
-
- if EffectiveResources.authorized?(self, :
|
7
|
+
- if EffectiveResources.authorized?(self, :all_committees, Effective::Committee)
|
8
8
|
Please
|
9
9
|
= link_to('click here', effective_committees.committees_path)
|
10
10
|
to view all #{committees_label.downcase}.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%h2 #{committees_label} Recent Activity
|
2
|
+
|
3
|
+
- if current_user.committees.present?
|
4
|
+
- current_user.committees_recent_activity(limit: 5).each do |logs|
|
5
|
+
- log = logs.first
|
6
|
+
|
7
|
+
- committee = log.changes_to
|
8
|
+
- link_to_committee = link_to(committee, effective_committees.committee_path(committee))
|
9
|
+
|
10
|
+
- committee_folder = log.associated.try(:committee_folder) || log.associated
|
11
|
+
- link_to_committee_folder = link_to(committee_folder, effective_committees.committee_committee_folder_path(committee, committee_folder))
|
12
|
+
|
13
|
+
- link_to_file = link_to(log.associated, url_for(log.associated.try(:file)))
|
14
|
+
|
15
|
+
- if logs.length == 1 && log.associated_type == 'Effective::CommitteeFolder'
|
16
|
+
%p Folder #{link_to_committee_folder} was added to #{link_to_committee}.
|
17
|
+
|
18
|
+
- elsif logs.length == 1 && log.associated_type == 'Effective::CommitteeFile'
|
19
|
+
%p File #{link_to_file} was added to #{link_to_committee} - #{link_to_committee_folder}.
|
20
|
+
|
21
|
+
- elsif logs.length > 1 && logs.all? { |log| log.associated_type == 'Effective::CommitteeFile' }
|
22
|
+
%p #{logs.length} files were added to #{link_to_committee} - #{link_to_committee_folder}.
|
23
|
+
|
24
|
+
- else
|
25
|
+
- raise("Unexpected logs: #{logs.inspect}")
|
26
|
+
|
27
|
+
%p= link_to('View more activity', effective_committees.activity_committees_path)
|
28
|
+
|
29
|
+
- else
|
30
|
+
%p There's no activity to display. When there is, we'll show it here.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
- committees = @committees.sorted
|
2
|
+
|
3
|
+
= render('layout') do
|
4
|
+
%nav{'aria-label': 'breadcrumb'}
|
5
|
+
%ol.breadcrumb
|
6
|
+
%li.breadcrumb-item= link_to("Home", root_path)
|
7
|
+
%li.breadcrumb-item.active{'aria-current': 'page'}= @page_title
|
8
|
+
|
9
|
+
%h1= @page_title
|
10
|
+
|
11
|
+
- if committees.blank?
|
12
|
+
%p There are no #{committees_label.downcase} to display.
|
13
|
+
- else
|
14
|
+
- datatable = EffectiveResources.best('EffectiveCommitteesActivityDatatable').new(self, namespace: :effective)
|
15
|
+
= render_datatable(datatable, inline: true)
|
16
|
+
.my-4
|
17
|
+
|
18
|
+
.form-actions
|
19
|
+
= link_to 'Continue', return_to_dashboard_path, class: 'btn btn-primary mb-4'
|
@@ -3,7 +3,7 @@
|
|
3
3
|
= render('layout') do
|
4
4
|
%nav{'aria-label': 'breadcrumb'}
|
5
5
|
%ol.breadcrumb
|
6
|
-
- if EffectiveResources.authorized?(self, :
|
6
|
+
- if EffectiveResources.authorized?(self, :all_committees, Effective::Committee)
|
7
7
|
%li.breadcrumb-item= link_to("All #{committees_label}", effective_committees.committees_path)
|
8
8
|
- else
|
9
9
|
%li.breadcrumb-item= link_to("Home", root_path)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
- resource = (@_effective_resource || Effective::Resource.new(controller_path))
|
2
|
+
- @resource = instance_variable_get('@' + resource.name) if resource.name
|
3
|
+
|
4
|
+
- if @resource
|
5
|
+
.resource-buttons
|
6
|
+
= render_resource_buttons(@resource, show: false)
|
7
|
+
|
8
|
+
= render_resource_partial(@resource)
|
9
|
+
|
10
|
+
.my-4
|
11
|
+
|
12
|
+
-# .form-actions
|
13
|
+
-# = link_to 'Continue', return_to_dashboard_path, class: 'btn btn-primary mb-4'
|
data/config/routes.rb
CHANGED
@@ -8,10 +8,13 @@ EffectiveCommittees::Engine.routes.draw do
|
|
8
8
|
# Public routes
|
9
9
|
scope module: 'effective' do
|
10
10
|
resources :committees, only: [:index, :show] do
|
11
|
+
get 'activity', on: :collection
|
12
|
+
|
11
13
|
resources :committee_folders, only: [:show]
|
12
14
|
end
|
13
15
|
|
14
16
|
get 'my-committees', to: 'committees#my_committees'
|
17
|
+
get 'my_committees', to: 'committees#my_committees'
|
15
18
|
|
16
19
|
resources :committee_members, except: [:show]
|
17
20
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_committees
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-09-
|
11
|
+
date: 2025-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -191,6 +191,7 @@ files:
|
|
191
191
|
- app/datatables/admin/effective_committee_members_datatable.rb
|
192
192
|
- app/datatables/admin/effective_committees_datatable.rb
|
193
193
|
- app/datatables/effective_committee_members_datatable.rb
|
194
|
+
- app/datatables/effective_committees_activity_datatable.rb
|
194
195
|
- app/datatables/effective_committees_datatable.rb
|
195
196
|
- app/helpers/effective_committees_helper.rb
|
196
197
|
- app/models/concerns/effective_committees_user.rb
|
@@ -207,16 +208,20 @@ files:
|
|
207
208
|
- app/views/admin/committees/_form_committee.html.haml
|
208
209
|
- app/views/effective/committee_folders/_committee_folder.html.haml
|
209
210
|
- app/views/effective/committee_folders/_layout.html.haml
|
211
|
+
- app/views/effective/committee_folders/show.html.haml
|
210
212
|
- app/views/effective/committee_members/_form.html.haml
|
211
213
|
- app/views/effective/committee_members/_user_fields.html.haml
|
212
214
|
- app/views/effective/committees/_committee.html.haml
|
213
215
|
- app/views/effective/committees/_dashboard.html.haml
|
216
|
+
- app/views/effective/committees/_dashboard_activity.html.haml
|
214
217
|
- app/views/effective/committees/_fields.html.haml
|
215
218
|
- app/views/effective/committees/_form.html.haml
|
216
219
|
- app/views/effective/committees/_form_committee.html.haml
|
217
220
|
- app/views/effective/committees/_layout.html.haml
|
221
|
+
- app/views/effective/committees/activity.html.haml
|
218
222
|
- app/views/effective/committees/index.html.haml
|
219
223
|
- app/views/effective/committees/my_committees.html.haml
|
224
|
+
- app/views/effective/committees/show.html.haml
|
220
225
|
- config/effective_committees.rb
|
221
226
|
- config/locales/effective_committees.en.yml
|
222
227
|
- config/routes.rb
|