effective_committees 0.9.5 → 0.10.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/admin/committee_agenda_items_controller.rb +16 -0
- data/app/controllers/effective/committee_agenda_items_controller.rb +11 -0
- data/app/controllers/effective/committee_folders_controller.rb +5 -0
- data/app/datatables/admin/effective_committee_agenda_items_datatable.rb +29 -0
- data/app/datatables/admin/effective_committee_folders_datatable.rb +10 -8
- data/app/helpers/effective_committees_helper.rb +11 -1
- data/app/models/effective/committee.rb +14 -2
- data/app/models/effective/committee_agenda_item.rb +43 -0
- data/app/models/effective/committee_folder.rb +59 -1
- data/app/views/admin/committee_agenda_items/_form.html.haml +3 -0
- data/app/views/admin/committee_agenda_items/_form_committee_agenda_item.html.haml +37 -0
- data/app/views/admin/committee_folders/_form.html.haml +21 -11
- data/app/views/admin/committee_folders/_form_committee_folder.html.haml +12 -2
- data/app/views/admin/committee_members/_form_committee_member.html.haml +8 -0
- data/app/views/admin/committees/_fields.html.haml +3 -0
- data/app/views/effective/committee_agenda_items/_card.html.haml +30 -0
- data/app/views/effective/committee_agenda_items/_committee_agenda_item.html.haml +14 -0
- data/app/views/effective/committee_agenda_items/show.html.haml +10 -0
- data/app/views/effective/committee_folders/_agenda.html.haml +42 -0
- data/app/views/effective/committee_folders/_breadcrumb.html.haml +13 -0
- data/app/views/effective/committee_folders/_committee_folder.html.haml +42 -20
- data/app/views/effective/committee_folders/agenda.html.haml +2 -0
- data/app/views/effective/committee_folders/show.html.haml +1 -1
- data/app/views/effective/committees/_dashboard_agendas.html.haml +18 -0
- data/app/views/effective/committees/index.html.haml +3 -0
- data/config/routes.rb +5 -1
- data/db/migrate/101_create_effective_committees.rb +25 -0
- data/lib/effective_committees/version.rb +1 -1
- data/lib/effective_committees.rb +1 -0
- metadata +15 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b64f9b12ecd4b0b3b70dd361f5fbe9c25b37009f167c68c92b7d0a0501bdbb7d
|
|
4
|
+
data.tar.gz: b3e5bbcadbd792f9f98d0bc5cb65aad229ae24fea3bae2aa7a0063f8e1535295
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 340c2c724dfab35ab4b3b901cd5035805496b4a7e6029abfaf3f490fbe957c1fdc99312c0fb72712577c2983083182baaf0c7a075baa08a5d9aae8c82b38a7fe
|
|
7
|
+
data.tar.gz: af0d65a2e6b320347dfd169ce5710712cda0eab4c33d80da5e386b8a2262e03b431d32ec922f8fa9a7579ab370a901811192bee4254c98e719856341b518e8b5
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class CommitteeAgendaItemsController < 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_agenda_item) ? :effective_committee_agenda_item : :committee_agenda_item)
|
|
12
|
+
params.require(model).permit!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Effective
|
|
2
|
+
class CommitteeAgendaItemsController < ApplicationController
|
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
4
|
+
|
|
5
|
+
include Effective::CrudController
|
|
6
|
+
log_page_views(if: -> { EffectiveCommittees.log_page_views? })
|
|
7
|
+
|
|
8
|
+
resource_scope -> { Effective::CommitteeAgendaItem.deep }
|
|
9
|
+
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class EffectiveCommitteeAgendaItemsDatatable < 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 :code, label: 'Code'
|
|
12
|
+
col :title
|
|
13
|
+
col :presenter
|
|
14
|
+
col :timed_at, label: 'Timed'
|
|
15
|
+
|
|
16
|
+
actions_col
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
collection do
|
|
20
|
+
scope = Effective::CommitteeAgendaItem.deep.sorted
|
|
21
|
+
|
|
22
|
+
if attributes[:committee_folder_id].present?
|
|
23
|
+
scope = scope.where(committee_folder_id: attributes[:committee_folder_id])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
scope
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -10,8 +10,8 @@ module Admin
|
|
|
10
10
|
|
|
11
11
|
col :committee
|
|
12
12
|
|
|
13
|
-
col :
|
|
14
|
-
|
|
13
|
+
col :title do |folder|
|
|
14
|
+
link_to(folder.title, effective_committees.edit_admin_committee_folder_path(folder))
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
col :slug, visible: false
|
|
@@ -24,18 +24,20 @@ module Admin
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
collection do
|
|
27
|
-
folders = Effective::CommitteeFolder.deep.sorted
|
|
27
|
+
folders = Effective::CommitteeFolder.deep.sorted
|
|
28
28
|
|
|
29
29
|
if attributes[:committee_folder_id].present?
|
|
30
|
-
folders = folders.where(
|
|
30
|
+
folders = folders.where(committee_folder_id: attributes[:committee_folder_id])
|
|
31
|
+
elsif attributes[:committee_id].present?
|
|
32
|
+
folders = folders.where(
|
|
33
|
+
committee_id: attributes[:committee_id],
|
|
34
|
+
committee_type: attributes[:committee_type],
|
|
35
|
+
committee_folder_id: nil
|
|
36
|
+
)
|
|
31
37
|
end
|
|
32
38
|
|
|
33
39
|
folders
|
|
34
40
|
end
|
|
35
41
|
|
|
36
|
-
def committee_folder
|
|
37
|
-
@committee_folder ||= Effective::CommitteeFolder.find_by_id(attributes[:committee_folder_id])
|
|
38
|
-
end
|
|
39
|
-
|
|
40
42
|
end
|
|
41
43
|
end
|
|
@@ -37,8 +37,18 @@ module EffectiveCommitteesHelper
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def admin_committees_parents(resource)
|
|
40
|
-
parents =
|
|
40
|
+
parents = []
|
|
41
|
+
parents << resource.committee if resource.respond_to?(:committee) && resource.committee.present?
|
|
42
|
+
parents += resource.parents
|
|
43
|
+
parents << resource
|
|
44
|
+
|
|
41
45
|
render(partial: 'admin/committees/parents', locals: { parents: parents }, formats: [:html])
|
|
42
46
|
end
|
|
43
47
|
|
|
48
|
+
def committee_file_link(committee_file, label: nil)
|
|
49
|
+
label = label.presence || committee_file.to_s
|
|
50
|
+
return label unless committee_file.file.attached?
|
|
51
|
+
link_to(label, url_for(committee_file.file), target: '_blank')
|
|
52
|
+
end
|
|
53
|
+
|
|
44
54
|
end
|
|
@@ -18,6 +18,8 @@ module Effective
|
|
|
18
18
|
has_many :committee_files, -> { Effective::CommitteeFile.sorted }, class_name: 'Effective::CommitteeFile', inverse_of: :committee, dependent: :delete_all
|
|
19
19
|
accepts_nested_attributes_for :committee_files, allow_destroy: true
|
|
20
20
|
|
|
21
|
+
has_many :committee_agenda_items, -> { Effective::CommitteeAgendaItem.sorted }, class_name: 'Effective::CommitteeAgendaItem', inverse_of: :committee, dependent: :delete_all
|
|
22
|
+
|
|
21
23
|
effective_resource do
|
|
22
24
|
title :string
|
|
23
25
|
slug :string
|
|
@@ -28,6 +30,8 @@ module Effective
|
|
|
28
30
|
committee_folders_count :integer # Counter Cache
|
|
29
31
|
committee_files_count :integer # Counter Cache
|
|
30
32
|
|
|
33
|
+
agenda_mode :boolean
|
|
34
|
+
|
|
31
35
|
timestamps
|
|
32
36
|
end
|
|
33
37
|
|
|
@@ -48,11 +52,19 @@ module Effective
|
|
|
48
52
|
title.presence || 'New Committee'
|
|
49
53
|
end
|
|
50
54
|
|
|
55
|
+
# Returns the user's currently-active term on this committee, or nil.
|
|
56
|
+
# For the full history including expired terms, use committee_members_for(user:).
|
|
51
57
|
def committee_member(user:)
|
|
52
|
-
committee_members.find { |member| member.user_id == user.id }
|
|
58
|
+
committee_members.find { |member| member.user_id == user.id && member.active? }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# All terms (active and expired) a user has served on this committee.
|
|
62
|
+
def committee_members_for(user:)
|
|
63
|
+
committee_members.select { |member| member.user_id == user.id }
|
|
53
64
|
end
|
|
54
65
|
|
|
55
|
-
# Find
|
|
66
|
+
# Find-active-or-build-new. If the user has no active term, build a fresh row
|
|
67
|
+
# (expired terms are history and are not edited in place through this helper).
|
|
56
68
|
def build_committee_member(user:)
|
|
57
69
|
committee_member(user: user) || committee_members.build(user: user)
|
|
58
70
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Effective
|
|
4
|
+
class CommitteeAgendaItem < ActiveRecord::Base
|
|
5
|
+
self.table_name = (EffectiveCommittees.committee_agenda_items_table_name || :committee_agenda_items).to_s
|
|
6
|
+
|
|
7
|
+
log_changes(to: :committee) if respond_to?(:log_changes)
|
|
8
|
+
|
|
9
|
+
belongs_to :committee, polymorphic: true
|
|
10
|
+
belongs_to :committee_folder
|
|
11
|
+
|
|
12
|
+
has_rich_text :body
|
|
13
|
+
|
|
14
|
+
effective_resource do
|
|
15
|
+
code :string
|
|
16
|
+
title :string
|
|
17
|
+
presenter :string
|
|
18
|
+
timed_at :string
|
|
19
|
+
|
|
20
|
+
position :integer
|
|
21
|
+
|
|
22
|
+
timestamps
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
before_validation(if: -> { committee_folder.present? }) do
|
|
26
|
+
self.committee ||= committee_folder.committee
|
|
27
|
+
self.position ||= (committee_folder.committee_agenda_items.maximum(:position) || -1) + 1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
scope :sorted, -> { order(:position) }
|
|
31
|
+
scope :deep, -> { includes(:rich_text_body) }
|
|
32
|
+
|
|
33
|
+
validates :title, presence: true, length: { maximum: 250 }
|
|
34
|
+
validates :position, presence: true
|
|
35
|
+
validates :code, length: { maximum: 50 }
|
|
36
|
+
validates :presenter, length: { maximum: 250 }
|
|
37
|
+
validates :timed_at, length: { maximum: 250 }
|
|
38
|
+
|
|
39
|
+
def to_s
|
|
40
|
+
[code, title].compact_blank.join(' ').presence || model_name.human
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -14,6 +14,8 @@ module Effective
|
|
|
14
14
|
has_many :committee_folders, -> { Effective::CommitteeFolder.sorted.deep }, dependent: :destroy, inverse_of: :committee_folder
|
|
15
15
|
has_many :committee_files, -> { Effective::CommitteeFile.sorted.deep }, dependent: :destroy, inverse_of: :committee_folder
|
|
16
16
|
|
|
17
|
+
has_many :committee_agenda_items, -> { Effective::CommitteeAgendaItem.sorted }, dependent: :destroy, inverse_of: :committee_folder
|
|
18
|
+
|
|
17
19
|
has_many_attached :files
|
|
18
20
|
|
|
19
21
|
effective_resource do
|
|
@@ -23,6 +25,8 @@ module Effective
|
|
|
23
25
|
position :integer
|
|
24
26
|
committee_files_count :integer # Counter Cache
|
|
25
27
|
|
|
28
|
+
meeting_date :datetime
|
|
29
|
+
|
|
26
30
|
timestamps
|
|
27
31
|
end
|
|
28
32
|
|
|
@@ -33,12 +37,52 @@ module Effective
|
|
|
33
37
|
scope :deep, -> { includes(:rich_text_body, :committee, :committee_files) }
|
|
34
38
|
scope :sorted, -> { order(:position) }
|
|
35
39
|
scope :top_level, -> { where(committee_folder_id: nil) }
|
|
40
|
+
scope :upcoming_meetings, -> { where.not(meeting_date: nil).where('meeting_date >= ?', 1.week.ago.beginning_of_day).order(:meeting_date) }
|
|
41
|
+
scope :past_meetings, -> { where.not(meeting_date: nil).where('meeting_date < ?', 1.week.ago.beginning_of_day).order(meeting_date: :desc) }
|
|
42
|
+
|
|
43
|
+
# Hierarchical alphabetical sort: roots A→Z, then each root's children A→Z, etc.
|
|
44
|
+
# Returns an Array so it can't be chained further; intended for select dropdowns.
|
|
45
|
+
scope :sorted_for_dropdowns, -> {
|
|
46
|
+
folders = order(:title).to_a
|
|
47
|
+
by_parent = folders.group_by(&:committee_folder_id)
|
|
48
|
+
visible_ids = folders.map(&:id).to_set
|
|
49
|
+
|
|
50
|
+
result = []
|
|
51
|
+
walk = ->(parent_id) {
|
|
52
|
+
Array(by_parent[parent_id]).each do |folder|
|
|
53
|
+
result << folder
|
|
54
|
+
walk.call(folder.id)
|
|
55
|
+
end
|
|
56
|
+
}
|
|
57
|
+
walk.call(nil)
|
|
58
|
+
|
|
59
|
+
# Any folders whose parent isn't in the current scope (e.g. the relation
|
|
60
|
+
# was filtered) should still appear, attached at the top in alphabetical order.
|
|
61
|
+
orphans = folders.reject { |folder| result.include?(folder) }
|
|
62
|
+
.reject { |folder| visible_ids.include?(folder.committee_folder_id) }
|
|
63
|
+
orphans.each do |folder|
|
|
64
|
+
result << folder
|
|
65
|
+
walk.call(folder.id)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
result
|
|
69
|
+
}
|
|
36
70
|
|
|
37
71
|
validates :title, presence: true, length: { maximum: 250 },
|
|
38
|
-
uniqueness: { scope: [:committee_id], message: 'already exists
|
|
72
|
+
uniqueness: { scope: [:committee_id, :committee_folder_id], message: 'already exists in this folder' }
|
|
39
73
|
|
|
40
74
|
validates :position, presence: true
|
|
41
75
|
|
|
76
|
+
validate(if: -> { meeting_date.present? }) do
|
|
77
|
+
if parents.any?(&:meeting?)
|
|
78
|
+
errors.add(:meeting_date, "can't be set — a parent folder is already an agenda")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if persisted? && committee_folders.any? { |child| child.meeting_date.present? || child.send(:any_descendant_meeting?) }
|
|
82
|
+
errors.add(:meeting_date, "can't be set — a child folder is already an agenda")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
42
86
|
def to_s
|
|
43
87
|
(parents + [self]).map { |folder| (folder.title || 'folder') }.join(' / ')
|
|
44
88
|
end
|
|
@@ -52,6 +96,14 @@ module Effective
|
|
|
52
96
|
committee_folder.blank?
|
|
53
97
|
end
|
|
54
98
|
|
|
99
|
+
def meeting?
|
|
100
|
+
meeting_date.present?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def agenda_section?
|
|
104
|
+
committee_folder&.meeting?
|
|
105
|
+
end
|
|
106
|
+
|
|
55
107
|
def parent
|
|
56
108
|
committee_folder || committee
|
|
57
109
|
end
|
|
@@ -72,5 +124,11 @@ module Effective
|
|
|
72
124
|
committee_folders.flat_map { |folder| [folder] + folder.children }
|
|
73
125
|
end
|
|
74
126
|
|
|
127
|
+
protected
|
|
128
|
+
|
|
129
|
+
def any_descendant_meeting?
|
|
130
|
+
committee_folders.any? { |child| child.meeting_date.present? || child.any_descendant_meeting? }
|
|
131
|
+
end
|
|
132
|
+
|
|
75
133
|
end
|
|
76
134
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
= effective_form_with(model: [:admin, committee_agenda_item], engine: true) do |f|
|
|
2
|
+
- f.object.committee_type ||= Effective::Committee.name
|
|
3
|
+
|
|
4
|
+
= f.hidden_field :committee_type
|
|
5
|
+
= f.hidden_field :committee_id
|
|
6
|
+
|
|
7
|
+
- if inline_datatable? && inline_datatable.attributes[:committee_folder_id].present?
|
|
8
|
+
= f.hidden_field :committee_folder_id
|
|
9
|
+
- elsif f.object.persisted?
|
|
10
|
+
= f.static_field :committee
|
|
11
|
+
= f.select :committee_folder_id, Effective::CommitteeFolder.sorted.where(committee: f.object.committee), label: "Section"
|
|
12
|
+
- else
|
|
13
|
+
= f.select :committee_id, Effective::Committee.sorted.all,
|
|
14
|
+
'data-load-ajax-url': effective_committees.new_admin_committee_agenda_item_path,
|
|
15
|
+
'data-load-ajax-div': '#effective-committees-ajax'
|
|
16
|
+
|
|
17
|
+
#effective-committees-ajax
|
|
18
|
+
= f.select :committee_folder_id, Effective::CommitteeFolder.sorted.where(committee: f.object.committee), label: "Section"
|
|
19
|
+
|
|
20
|
+
.row
|
|
21
|
+
.col-md-3
|
|
22
|
+
= f.text_field :code, hint: "e.g. A-1"
|
|
23
|
+
.col-md-9
|
|
24
|
+
= f.text_field :title
|
|
25
|
+
|
|
26
|
+
.row
|
|
27
|
+
.col-md-6
|
|
28
|
+
= f.text_field :presenter
|
|
29
|
+
.col-md-6
|
|
30
|
+
= f.text_field :timed_at, label: "Time", hint: "e.g. 3:00pm"
|
|
31
|
+
|
|
32
|
+
- if defined?(EffectiveArticleEditor)
|
|
33
|
+
= f.article_editor :body
|
|
34
|
+
- else
|
|
35
|
+
= f.rich_text_area :body, hint: "Rich text shown under the item title."
|
|
36
|
+
|
|
37
|
+
= f.submit
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
- if committee_folder.persisted?
|
|
2
2
|
%p= admin_committees_parents(committee_folder)
|
|
3
3
|
|
|
4
|
+
- agenda_section = committee_folder.committee.agenda_mode? && committee_folder.agenda_section?
|
|
5
|
+
|
|
4
6
|
= tabs do
|
|
5
7
|
- if committee_folder.persisted?
|
|
6
8
|
= tab 'Folder' do
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
%
|
|
9
|
+
- if agenda_section
|
|
10
|
+
%h3 Agenda Items
|
|
11
|
+
%p.text-muted
|
|
12
|
+
%small Structured items rendered on the agenda page. Drag the reorder handle to change position.
|
|
13
|
+
|
|
14
|
+
- datatable = Admin::EffectiveCommitteeAgendaItemsDatatable.new(committee_folder_id: committee_folder.id, committee_id: committee_folder.committee_id, committee_type: committee_folder.committee_type)
|
|
15
|
+
= render_datatable(datatable, inline: true)
|
|
16
|
+
- else
|
|
17
|
+
%h3 Folders
|
|
18
|
+
%p.text-muted
|
|
19
|
+
%small Refresh the page after creating a new folder to move files to it.
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
- datatable = Admin::EffectiveCommitteeFoldersDatatable.new(committee_folder: committee_folder, committee: committee_folder.committee)
|
|
22
|
+
= render_datatable(datatable, inline: true, simple: true)
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
%h3 Files
|
|
25
|
+
%p.text-muted
|
|
26
|
+
%small Select the files, then use the Bulk Actions dropdown to move them to another folder
|
|
17
27
|
|
|
18
|
-
|
|
28
|
+
.mt-4= render('admin/committee_folders/form_bulk_upload', committee_folder: committee_folder)
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
- datatable = Admin::EffectiveCommitteeFilesDatatable.new(committee_folder: committee_folder, committee: committee_folder.committee)
|
|
31
|
+
= render_datatable(datatable, inline: true)
|
|
22
32
|
|
|
23
33
|
= tab 'Folder Details' do
|
|
24
34
|
= render 'admin/committee_folders/form_committee_folder', committee_folder: committee_folder
|
|
@@ -8,22 +8,32 @@
|
|
|
8
8
|
= f.hidden_field :committee_folder_id
|
|
9
9
|
- elsif f.object.persisted?
|
|
10
10
|
= f.static_field :committee
|
|
11
|
-
= f.select :committee_folder_id, Effective::CommitteeFolder.
|
|
11
|
+
= f.select :committee_folder_id, Effective::CommitteeFolder.where(committee: f.object.committee).sorted_for_dropdowns, label: "Parent Folder", hint: "Leave blank to create a top-level folder"
|
|
12
12
|
- else
|
|
13
13
|
= f.select :committee_id, Effective::Committee.sorted.all,
|
|
14
14
|
'data-load-ajax-url': effective_committees.new_admin_committee_folder_path,
|
|
15
15
|
'data-load-ajax-div': '#effective-committees-ajax'
|
|
16
16
|
|
|
17
17
|
#effective-committees-ajax
|
|
18
|
-
= f.select :committee_folder_id, Effective::CommitteeFolder.
|
|
18
|
+
= f.select :committee_folder_id, Effective::CommitteeFolder.where(committee: f.object.committee).sorted_for_dropdowns, label: "Parent Folder", hint: "Leave blank to create a top-level folder"
|
|
19
19
|
|
|
20
20
|
= f.text_field :title
|
|
21
21
|
|
|
22
22
|
= acts_as_slugged_fields(f, url: (effective_committees.commitee_url(f.object) rescue nil))
|
|
23
23
|
|
|
24
|
+
- if f.object.committee&.agenda_mode?
|
|
25
|
+
- meeting_ancestor = f.object.parents.detect(&:meeting?)
|
|
26
|
+
- if meeting_ancestor.present?
|
|
27
|
+
.alert.alert-info.mb-3
|
|
28
|
+
This folder is inside the “#{meeting_ancestor.title}” agenda, so it can’t be turned into its own agenda. It should be treated as a section of the parent agenda.
|
|
29
|
+
- else
|
|
30
|
+
= f.datetime_field :meeting_date, label: "Meeting date & time",
|
|
31
|
+
hint: "Turns this folder into an agenda. Child folders become the agenda's sections (A, B, C, etc.), and within each section folder you can add agenda items. Details added to the Body below will appear at the top of the agenda page.".html_safe
|
|
32
|
+
|
|
24
33
|
- if defined?(EffectiveArticleEditor)
|
|
25
34
|
= f.article_editor :body, hint: "Displayed on the #{committee_folder_label} page"
|
|
26
35
|
- else
|
|
27
36
|
= f.rich_text_area :body, hint: "Displayed on the #{committee_folder_label} page"
|
|
28
37
|
|
|
38
|
+
|
|
29
39
|
= f.submit
|
|
@@ -25,6 +25,14 @@
|
|
|
25
25
|
= f.static_field :committee
|
|
26
26
|
= f.static_field :user, label: committee_member_label
|
|
27
27
|
|
|
28
|
+
- other_terms = f.object.committee.committee_members_for(user: f.object.user).reject { |m| m.id == f.object.id }
|
|
29
|
+
- if other_terms.any?
|
|
30
|
+
.mb-3
|
|
31
|
+
%strong Other terms for this user on this committee
|
|
32
|
+
%ul
|
|
33
|
+
- other_terms.each do |term|
|
|
34
|
+
%li= [term.start_on || '(open start)', term.end_on || '(open end)'].join(' to ')
|
|
35
|
+
|
|
28
36
|
= f.text_field :category
|
|
29
37
|
|
|
30
38
|
.row
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
= f.check_box :display_on_index, label: "Show on the member-only #{link_to "Volunteers and Committees", effective_committees.volunteers_and_committees_path, target: '_blank'} page"
|
|
6
6
|
= f.check_box :display_on_dashboard, label: "Show on the #{link_to "My #{committee_label.pluralize}", effective_committees.committees_path, target: '_blank'} page".html_safe
|
|
7
7
|
|
|
8
|
+
= f.check_box :agenda_mode, label: "Enable structured meeting agendas for this #{committee_label}",
|
|
9
|
+
hint: "When checked, any subfolder with a meeting date has the meeting agenda view enabled.".html_safe
|
|
10
|
+
|
|
8
11
|
- if defined?(EffectiveArticleEditor)
|
|
9
12
|
= f.article_editor :body, hint: "Shown on the #{committee_label} page."
|
|
10
13
|
- else
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-# Renders a single agenda item's content (left column + right metadata column).
|
|
2
|
+
-# Locals:
|
|
3
|
+
-# item: CommitteeAgendaItem
|
|
4
|
+
-# compact: true when rendered in the long agenda list (smaller heading)
|
|
5
|
+
|
|
6
|
+
- compact = local_assigns.fetch(:compact, false)
|
|
7
|
+
|
|
8
|
+
.row
|
|
9
|
+
.col-md-9
|
|
10
|
+
- if compact
|
|
11
|
+
%h4.mb-2
|
|
12
|
+
- if item.code.present?
|
|
13
|
+
%span.text-muted.me-2= item.code
|
|
14
|
+
= item.title
|
|
15
|
+
- else
|
|
16
|
+
%h1.card-title.mb-2
|
|
17
|
+
- if item.code.present?
|
|
18
|
+
%span.text-muted.me-2= item.code
|
|
19
|
+
= item.title
|
|
20
|
+
|
|
21
|
+
- if item.body.present?
|
|
22
|
+
.agenda-item-body= item.body.to_s
|
|
23
|
+
|
|
24
|
+
.col-md-3.text-md-end
|
|
25
|
+
- if item.presenter.present?
|
|
26
|
+
%p.mb-1
|
|
27
|
+
%strong= item.presenter
|
|
28
|
+
- if item.timed_at.present?
|
|
29
|
+
%p.mb-0.text-muted
|
|
30
|
+
%em= item.timed_at
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
- committee = committee_agenda_item.committee
|
|
2
|
+
- section = committee_agenda_item.committee_folder
|
|
3
|
+
|
|
4
|
+
- trail = section.parents.map { |parent| [parent.title, effective_committees.committee_committee_folder_path(committee, parent)] }
|
|
5
|
+
- trail << [section.title, effective_committees.committee_committee_folder_path(committee, section)]
|
|
6
|
+
= render 'effective/committee_folders/breadcrumb', committee: committee, trail: trail, current: committee_agenda_item.to_s
|
|
7
|
+
|
|
8
|
+
.effective-committee-agenda-item
|
|
9
|
+
.card.mb-4
|
|
10
|
+
.card-body
|
|
11
|
+
= render 'effective/committee_agenda_items/card', item: committee_agenda_item
|
|
12
|
+
|
|
13
|
+
%p
|
|
14
|
+
= link_to "← Back", effective_committees.committee_committee_folder_path(committee, section), class: 'btn btn-link p-0'
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
- committee = committee_folder.committee
|
|
2
|
+
- sections = committee_folder.committee_folders.sorted.includes(:rich_text_body, committee_agenda_items: :rich_text_body)
|
|
3
|
+
|
|
4
|
+
- trail = committee_folder.parents.map { |parent| [parent.title, effective_committees.committee_committee_folder_path(committee, parent)] }
|
|
5
|
+
= render 'effective/committee_folders/breadcrumb', committee: committee, trail: trail, current: committee_folder.title
|
|
6
|
+
|
|
7
|
+
.effective-committee-agenda
|
|
8
|
+
%h1.mb-1= committee.to_s
|
|
9
|
+
%h2.text-muted.mb-3= committee_folder.title
|
|
10
|
+
|
|
11
|
+
.card.mb-4
|
|
12
|
+
.card-body
|
|
13
|
+
|
|
14
|
+
- if committee_folder.meeting_date.present?
|
|
15
|
+
%p.mb-3
|
|
16
|
+
%strong Date:
|
|
17
|
+
= committee_folder.meeting_date.strftime('%A, %B %-d, %Y at %-l:%M %p')
|
|
18
|
+
|
|
19
|
+
- if committee_folder.rich_text_body.present?
|
|
20
|
+
= committee_folder.rich_text_body.to_s
|
|
21
|
+
|
|
22
|
+
- sections.each do |section|
|
|
23
|
+
%section.mb-5{id: "section-#{section.id}"}
|
|
24
|
+
%h2.mb-3= section.title
|
|
25
|
+
- if section.rich_text_body.present?
|
|
26
|
+
.mb-3= section.rich_text_body.to_s
|
|
27
|
+
|
|
28
|
+
- items = section.committee_agenda_items.sorted
|
|
29
|
+
- if items.any?
|
|
30
|
+
.card
|
|
31
|
+
.list-group.list-group-flush
|
|
32
|
+
- items.each do |item|
|
|
33
|
+
.list-group-item{id: "item-#{item.id}"}
|
|
34
|
+
= render 'effective/committee_agenda_items/card', item: item, compact: true
|
|
35
|
+
|
|
36
|
+
- meeting_files = committee_folder.committee_files.sorted
|
|
37
|
+
- if meeting_files.any?
|
|
38
|
+
%hr
|
|
39
|
+
%h3 Meeting Files
|
|
40
|
+
%ul
|
|
41
|
+
- meeting_files.each do |committee_file|
|
|
42
|
+
%li= committee_file_link(committee_file)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-# Locals:
|
|
2
|
+
-# committee: the Committee
|
|
3
|
+
-# trail: [[title, path], ...] — non-active links between the committee and the active page
|
|
4
|
+
-# current: title string of the active leaf
|
|
5
|
+
|
|
6
|
+
%nav{'aria-label': 'breadcrumb'}
|
|
7
|
+
%ol.breadcrumb
|
|
8
|
+
%li.breadcrumb-item= link_to("My Dashboard", return_to_dashboard_path)
|
|
9
|
+
%li.breadcrumb-item= link_to("My #{committees_label}", effective_committees.committees_path)
|
|
10
|
+
%li.breadcrumb-item= link_to(committee, effective_committees.committee_path(committee))
|
|
11
|
+
- trail.each do |title, path|
|
|
12
|
+
%li.breadcrumb-item= link_to(title, path)
|
|
13
|
+
%li.breadcrumb-item.active{'aria-current': 'page'}= current
|
|
@@ -1,31 +1,54 @@
|
|
|
1
1
|
= render('layout') do
|
|
2
2
|
- committee = committee_folder.committee
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
%li.breadcrumb-item= link_to("My Dashboard", return_to_dashboard_path)
|
|
7
|
-
%li.breadcrumb-item= link_to("My #{committees_label}", effective_committees.committees_path)
|
|
8
|
-
%li.breadcrumb-item= link_to(committee, effective_committees.committee_path(committee))
|
|
9
|
-
|
|
10
|
-
- committee_folder.parents.each do |parent|
|
|
11
|
-
%li.breadcrumb-item= link_to(parent.title, effective_committees.committee_committee_folder_path(committee, parent))
|
|
12
|
-
|
|
13
|
-
%li.breadcrumb-item.active{'aria-current': 'page'}= committee_folder.title
|
|
4
|
+
- trail = committee_folder.parents.map { |parent| [parent.title, effective_committees.committee_committee_folder_path(committee, parent)] }
|
|
5
|
+
= render 'effective/committee_folders/breadcrumb', committee: committee, trail: trail, current: committee_folder.title
|
|
14
6
|
|
|
15
7
|
.effective-committee-folder
|
|
16
|
-
|
|
8
|
+
.d-flex.justify-content-between.align-items-start.mb-3
|
|
9
|
+
%h1.mb-0= committee_folder.title
|
|
10
|
+
- if committee.agenda_mode? && committee_folder.meeting?
|
|
11
|
+
= link_to "View Agenda", effective_committees.agenda_committee_committee_folder_path(committee, committee_folder), class: 'btn btn-primary'
|
|
17
12
|
|
|
18
13
|
- if committee_folder.rich_text_body.present?
|
|
19
14
|
.mb-4= committee_folder.rich_text_body.to_s
|
|
20
15
|
|
|
21
16
|
.my-4
|
|
22
17
|
|
|
18
|
+
- agenda_items = committee_folder.committee_agenda_items.sorted if committee.agenda_mode?
|
|
19
|
+
|
|
20
|
+
- if committee.agenda_mode? && agenda_items.present?
|
|
21
|
+
%h3 Agenda Items
|
|
22
|
+
.card.mb-4
|
|
23
|
+
.list-group.list-group-flush
|
|
24
|
+
- agenda_items.each do |agenda_item|
|
|
25
|
+
= link_to(effective_committees.committee_committee_folder_committee_agenda_item_path(committee, committee_folder, agenda_item), class: 'list-group-item list-group-action') do
|
|
26
|
+
.row
|
|
27
|
+
.col-md-9
|
|
28
|
+
- if agenda_item.code.present?
|
|
29
|
+
%span.text-muted.me-2= agenda_item.code
|
|
30
|
+
= agenda_item.title
|
|
31
|
+
.col-md-3.text-md-end
|
|
32
|
+
- if agenda_item.presenter.present?
|
|
33
|
+
%small.text-muted= agenda_item.presenter
|
|
34
|
+
- if agenda_item.timed_at.present?
|
|
35
|
+
%small.text-muted.ms-2= agenda_item.timed_at
|
|
36
|
+
|
|
37
|
+
- meeting_children = committee_folder.committee_folders.select(&:meeting?) if committee.agenda_mode?
|
|
38
|
+
|
|
39
|
+
- if committee.agenda_mode? && meeting_children.present?
|
|
40
|
+
%h3 Agendas
|
|
41
|
+
.card.mb-4
|
|
42
|
+
.list-group.list-group-flush
|
|
43
|
+
- meeting_children.each do |meeting_folder|
|
|
44
|
+
= link_to(meeting_folder.title, effective_committees.agenda_committee_committee_folder_path(committee, meeting_folder), class: 'list-group-item list-group-action')
|
|
45
|
+
|
|
23
46
|
- if committee_folder.committee_folders.present?
|
|
24
47
|
%h3 Folders
|
|
25
|
-
.card
|
|
48
|
+
.card.mb-4
|
|
26
49
|
.list-group.list-group-flush
|
|
27
|
-
- committee_folder.committee_folders.each do |
|
|
28
|
-
= link_to(
|
|
50
|
+
- committee_folder.committee_folders.each do |child_folder|
|
|
51
|
+
= link_to(child_folder.title, effective_committees.committee_committee_folder_path(committee, child_folder), class: 'list-group-item list-group-action')
|
|
29
52
|
|
|
30
53
|
%h3 Files
|
|
31
54
|
.card
|
|
@@ -43,14 +66,13 @@
|
|
|
43
66
|
- committee_folder.committee_files.each_with_index do |file, index|
|
|
44
67
|
%tr
|
|
45
68
|
%td= index+1
|
|
46
|
-
%td
|
|
47
|
-
- if file.file.attached?
|
|
48
|
-
= link_to(file.to_s, url_for(file.file), target: '_blank')
|
|
49
|
-
- else
|
|
50
|
-
= file.to_s
|
|
51
|
-
|
|
69
|
+
%td= committee_file_link(file)
|
|
52
70
|
%td.d-none.d-lg-table-cell= file.created_at.strftime('%F')
|
|
53
71
|
%td.d-none.d-lg-table-cell= number_to_human_size(file.file.byte_size)
|
|
54
72
|
%td.d-none.d-lg-table-cell= file.notes
|
|
55
73
|
- else
|
|
56
74
|
%p No files.
|
|
75
|
+
|
|
76
|
+
- back_path = committee_folder.committee_folder.present? ? effective_committees.committee_committee_folder_path(committee, committee_folder.committee_folder) : effective_committees.committee_path(committee)
|
|
77
|
+
%p.mt-4
|
|
78
|
+
= link_to "← Back", back_path, class: 'btn btn-link p-0'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
- agenda_committees = current_user.committees.select(&:agenda_mode?)
|
|
2
|
+
- upcoming = agenda_committees.flat_map { |c| Effective::CommitteeFolder.where(committee: c).upcoming_meetings.limit(5) }.sort_by(&:meeting_date).first(5)
|
|
3
|
+
|
|
4
|
+
- if upcoming.any? || recent.any?
|
|
5
|
+
%h3 Upcoming Meetings
|
|
6
|
+
|
|
7
|
+
- if upcoming.any?
|
|
8
|
+
.card
|
|
9
|
+
.list-group.list-group-flush
|
|
10
|
+
- upcoming.each do |meeting|
|
|
11
|
+
= link_to effective_committees.agenda_committee_committee_folder_path(meeting.committee, meeting), class: 'list-group-item list-group-action' do
|
|
12
|
+
%strong= meeting.committee.to_s
|
|
13
|
+
%br
|
|
14
|
+
= meeting.title
|
|
15
|
+
- else
|
|
16
|
+
%p.text-muted No upcoming meetings.
|
|
17
|
+
|
|
18
|
+
.mb-5
|
data/config/routes.rb
CHANGED
|
@@ -10,7 +10,10 @@ EffectiveCommittees::Engine.routes.draw do
|
|
|
10
10
|
resources :committees, only: [:index, :show] do
|
|
11
11
|
get 'activity', on: :collection
|
|
12
12
|
|
|
13
|
-
resources :committee_folders, only: [:show]
|
|
13
|
+
resources :committee_folders, only: [:show], path: 'folders' do
|
|
14
|
+
member { get :agenda }
|
|
15
|
+
resources :committee_agenda_items, only: [:show]
|
|
16
|
+
end
|
|
14
17
|
end
|
|
15
18
|
|
|
16
19
|
get 'volunteers-and-committees', to: 'committees#volunteers_and_committees', as: 'volunteers_and_committees'
|
|
@@ -26,6 +29,7 @@ EffectiveCommittees::Engine.routes.draw do
|
|
|
26
29
|
resources :committee_files, except: [:show] do
|
|
27
30
|
post :bulk_move, on: :collection
|
|
28
31
|
end
|
|
32
|
+
resources :committee_agenda_items, except: [:show, :index]
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
end
|
|
@@ -13,6 +13,8 @@ class CreateEffectiveCommittees < ActiveRecord::Migration[6.0]
|
|
|
13
13
|
t.boolean :display_on_index, default: true
|
|
14
14
|
t.boolean :display_on_dashboard, default: true
|
|
15
15
|
|
|
16
|
+
t.boolean :agenda_mode, default: false, null: false
|
|
17
|
+
|
|
16
18
|
t.datetime :updated_at
|
|
17
19
|
t.datetime :created_at
|
|
18
20
|
end
|
|
@@ -57,6 +59,8 @@ class CreateEffectiveCommittees < ActiveRecord::Migration[6.0]
|
|
|
57
59
|
t.integer :position
|
|
58
60
|
t.integer :committee_files_count, default: 0
|
|
59
61
|
|
|
62
|
+
t.datetime :meeting_date
|
|
63
|
+
|
|
60
64
|
t.datetime :updated_at
|
|
61
65
|
t.datetime :created_at
|
|
62
66
|
end
|
|
@@ -64,6 +68,7 @@ class CreateEffectiveCommittees < ActiveRecord::Migration[6.0]
|
|
|
64
68
|
add_index :committee_folders, [:committee_id, :committee_type]
|
|
65
69
|
add_index :committee_folders, [:position]
|
|
66
70
|
add_index :committee_folders, :committee_id, if_not_exists: true
|
|
71
|
+
add_index :committee_folders, [:committee_id, :meeting_date]
|
|
67
72
|
|
|
68
73
|
create_table :committee_files do |t|
|
|
69
74
|
t.integer :committee_id
|
|
@@ -85,5 +90,25 @@ class CreateEffectiveCommittees < ActiveRecord::Migration[6.0]
|
|
|
85
90
|
|
|
86
91
|
add_index :committee_files, :committee_id, if_not_exists: true
|
|
87
92
|
add_index :committee_files, :title, if_not_exists: true
|
|
93
|
+
|
|
94
|
+
create_table :committee_agenda_items do |t|
|
|
95
|
+
t.integer :committee_id
|
|
96
|
+
t.string :committee_type
|
|
97
|
+
|
|
98
|
+
t.integer :committee_folder_id
|
|
99
|
+
|
|
100
|
+
t.string :code
|
|
101
|
+
t.string :title
|
|
102
|
+
t.string :presenter
|
|
103
|
+
t.string :timed_at
|
|
104
|
+
|
|
105
|
+
t.integer :position
|
|
106
|
+
|
|
107
|
+
t.datetime :updated_at
|
|
108
|
+
t.datetime :created_at
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
add_index :committee_agenda_items, :committee_folder_id
|
|
112
|
+
add_index :committee_agenda_items, [:committee_id, :committee_type]
|
|
88
113
|
end
|
|
89
114
|
end
|
data/lib/effective_committees.rb
CHANGED
|
@@ -9,6 +9,7 @@ module EffectiveCommittees
|
|
|
9
9
|
def self.config_keys
|
|
10
10
|
[
|
|
11
11
|
:committees_table_name, :committee_members_table_name, :committee_folders_table_name, :committee_files_table_name,
|
|
12
|
+
:committee_agenda_items_table_name,
|
|
12
13
|
:layout, :use_effective_roles, :log_page_views
|
|
13
14
|
]
|
|
14
15
|
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.10.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: 2026-
|
|
11
|
+
date: 2026-05-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -207,13 +207,16 @@ files:
|
|
|
207
207
|
- app/assets/javascripts/effective_committees/base.js
|
|
208
208
|
- app/assets/stylesheets/effective_committees.scss
|
|
209
209
|
- app/assets/stylesheets/effective_committees/base.scss
|
|
210
|
+
- app/controllers/admin/committee_agenda_items_controller.rb
|
|
210
211
|
- app/controllers/admin/committee_files_controller.rb
|
|
211
212
|
- app/controllers/admin/committee_folders_controller.rb
|
|
212
213
|
- app/controllers/admin/committee_members_controller.rb
|
|
213
214
|
- app/controllers/admin/committees_controller.rb
|
|
215
|
+
- app/controllers/effective/committee_agenda_items_controller.rb
|
|
214
216
|
- app/controllers/effective/committee_folders_controller.rb
|
|
215
217
|
- app/controllers/effective/committee_members_controller.rb
|
|
216
218
|
- app/controllers/effective/committees_controller.rb
|
|
219
|
+
- app/datatables/admin/effective_committee_agenda_items_datatable.rb
|
|
217
220
|
- app/datatables/admin/effective_committee_files_datatable.rb
|
|
218
221
|
- app/datatables/admin/effective_committee_folders_datatable.rb
|
|
219
222
|
- app/datatables/admin/effective_committee_members_datatable.rb
|
|
@@ -224,9 +227,12 @@ files:
|
|
|
224
227
|
- app/helpers/effective_committees_helper.rb
|
|
225
228
|
- app/models/concerns/effective_committees_user.rb
|
|
226
229
|
- app/models/effective/committee.rb
|
|
230
|
+
- app/models/effective/committee_agenda_item.rb
|
|
227
231
|
- app/models/effective/committee_file.rb
|
|
228
232
|
- app/models/effective/committee_folder.rb
|
|
229
233
|
- app/models/effective/committee_member.rb
|
|
234
|
+
- app/views/admin/committee_agenda_items/_form.html.haml
|
|
235
|
+
- app/views/admin/committee_agenda_items/_form_committee_agenda_item.html.haml
|
|
230
236
|
- app/views/admin/committee_files/_form.html.haml
|
|
231
237
|
- app/views/admin/committee_files/_form_committee_file.html.haml
|
|
232
238
|
- app/views/admin/committee_folders/_form.html.haml
|
|
@@ -239,14 +245,21 @@ files:
|
|
|
239
245
|
- app/views/admin/committees/_form.html.haml
|
|
240
246
|
- app/views/admin/committees/_form_committee.html.haml
|
|
241
247
|
- app/views/admin/committees/_parents.html.haml
|
|
248
|
+
- app/views/effective/committee_agenda_items/_card.html.haml
|
|
249
|
+
- app/views/effective/committee_agenda_items/_committee_agenda_item.html.haml
|
|
250
|
+
- app/views/effective/committee_agenda_items/show.html.haml
|
|
251
|
+
- app/views/effective/committee_folders/_agenda.html.haml
|
|
252
|
+
- app/views/effective/committee_folders/_breadcrumb.html.haml
|
|
242
253
|
- app/views/effective/committee_folders/_committee_folder.html.haml
|
|
243
254
|
- app/views/effective/committee_folders/_layout.html.haml
|
|
255
|
+
- app/views/effective/committee_folders/agenda.html.haml
|
|
244
256
|
- app/views/effective/committee_folders/show.html.haml
|
|
245
257
|
- app/views/effective/committee_members/_form.html.haml
|
|
246
258
|
- app/views/effective/committee_members/_user_fields.html.haml
|
|
247
259
|
- app/views/effective/committees/_committee.html.haml
|
|
248
260
|
- app/views/effective/committees/_dashboard.html.haml
|
|
249
261
|
- app/views/effective/committees/_dashboard_activity.html.haml
|
|
262
|
+
- app/views/effective/committees/_dashboard_agendas.html.haml
|
|
250
263
|
- app/views/effective/committees/_fields.html.haml
|
|
251
264
|
- app/views/effective/committees/_form.html.haml
|
|
252
265
|
- app/views/effective/committees/_form_committee.html.haml
|