effective_memberships 0.9.7 → 0.9.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9916218e0d606b59b230debdc5c7a70e1d3754333f786298a4b9f3cf21222ce
4
- data.tar.gz: 7ee9f5e5f4f64ea6764c206b053a81dc0d253a596de57d2e20324e3c64b86aa4
3
+ metadata.gz: 612909b87d53748d9b3488893e419cf6f8bdcb852fdb07d3bd0f015bda89771c
4
+ data.tar.gz: 7c48d16e502036542d4f80e785986134e19466593b44ecce9cef151e76387acc
5
5
  SHA512:
6
- metadata.gz: 6e6f8b7f49df86cd4461dba072f3106e3a095076d44f298ced308857e7ee86b3f91455d6823716470d6b4dccdb75ed42e8e05cc2be9bc0208e314aaef011e759
7
- data.tar.gz: 936b9c462cede66151ae4a9d186a3b3d6aee60989f284f6157373fb043f73498e486678e09d39af0f75f648a5ace5826f66f0ec553427fbeb77375a1b5822fa9
6
+ metadata.gz: 835021e63b547f68e17ae9bd9ca6bbc523217e1f4f7c3eaf100696ef4456fb63b4f384765cad26db941aca67203ddb87e157ac64620e41220f98571a23d9074b
7
+ data.tar.gz: 706ec5a09d03a23f5495ccae6ec1f28fb930a4a1533a41b15f6f9a859f6e1bbb1d19dd9df0f83e0e6a56fb0bd6abe6d378576e5d1d439a2fa9ebaa3adfec2d69
@@ -16,6 +16,15 @@ module Effective
16
16
  @memberships = @membership_directory.results(page: params[:page])
17
17
  end
18
18
 
19
+ def show
20
+ @page_title = 'Directory'
21
+
22
+ @membership = Effective::Membership.find_by_token(params[:id])
23
+
24
+ EffectiveResources.authorize!(self, :show, @membership)
25
+ EffectiveResources.authorize!(self, :show, @membership.owner)
26
+ end
27
+
19
28
  def build_membership_directory
20
29
  directory = EffectiveMemberships.MembershipDirectory.new(search_params)
21
30
  directory.current_user = current_user
@@ -63,7 +63,7 @@ module Admin
63
63
  end
64
64
 
65
65
  collection do
66
- EffectiveMemberships.Organization.deep.left_joins(:membership).includes(:addresses, membership: :membership_categories)
66
+ EffectiveMemberships.Organization.deep.left_joins(:membership).includes(:addresses, membership: [membership_categories: :category], representatives: :user)
67
67
  end
68
68
 
69
69
  def categories
@@ -3,25 +3,25 @@ class EffectiveMembershipsDirectoryDatatable < Effective::Datatable
3
3
  datatable do
4
4
  length 100
5
5
 
6
- col(:name) { |membership| membership.owner.to_s }
7
-
6
+ col :owner_name, label: 'Name'
8
7
  col :joined_on
9
8
  col :number
10
- col :categories, search: :string, label: 'Category'
11
- end
12
-
13
- collection do
14
- scope = Effective::Membership.directory.all
15
9
 
16
- archived_klasses.each do |klass|
17
- scope = scope.where.not(owner_id: klass.archived.select('id'), owner_type: klass.name)
10
+ col(:categories, search: categories, label: 'Category', sql_column: true).search do |collection, term|
11
+ collection.with_category(EffectiveMemberships.Category.find(term))
18
12
  end
19
13
 
20
- scope
21
14
  end
22
15
 
23
- def archived_klasses
24
- @archived_klasses ||= Effective::Membership.owner_klasses.select { |klass| klass.try(:acts_as_archived?) }
16
+ collection do
17
+ Effective::Membership.deep.sorted
18
+ .in_good_standing
19
+ .without_archived_owners
20
+ .with_category(categories)
21
+ end
22
+
23
+ def categories
24
+ EffectiveMemberships.Category.membership_directory.all
25
25
  end
26
26
 
27
27
  end
@@ -114,6 +114,9 @@ module EffectiveMembershipsCategory
114
114
  .or(where(can_apply_restricted: true))
115
115
  }
116
116
 
117
+ # Can be used to limit which memberships are displayed in the directory
118
+ scope :membership_directory, -> { sorted }
119
+
117
120
  validates :title, presence: true, uniqueness: true
118
121
  validates :category_type, presence: true
119
122
  validates :position, presence: true
@@ -19,18 +19,29 @@ module EffectiveMembershipsDirectory
19
19
  attr_accessor :term
20
20
  attr_accessor :category
21
21
 
22
+ # Users
22
23
  attr_accessor :first_name
23
24
  attr_accessor :last_name
24
25
 
26
+ # Organizations
27
+ attr_accessor :title
28
+
25
29
  validates :term, length: { minimum: 3, allow_blank: true }
26
30
  validates :first_name, length: { minimum: 2, allow_blank: true }
27
31
  validates :last_name, length: { minimum: 2, allow_blank: true }
32
+ validates :title, length: { minimum: 2, allow_blank: true }
33
+ end
34
+
35
+ def categories
36
+ EffectiveMemberships.Category.membership_directory.all
28
37
  end
29
38
 
30
39
  # Base collection to search. Can be configured per tenant.
31
40
  def collection
32
- # Example::User.members.membership_in_good_standing.all
33
- raise('to be implemented by app membership_directory')
41
+ Effective::Membership.deep.sorted
42
+ .in_good_standing
43
+ .without_archived_owners
44
+ .with_category(categories)
34
45
  end
35
46
 
36
47
  # Search Users and Organizations for only these fields. Passed into search_any. Return nil for all.
@@ -44,21 +55,21 @@ module EffectiveMembershipsDirectory
44
55
  end
45
56
 
46
57
  def present?
47
- term.present? || first_name.present? || last_name.present? || category.present?
58
+ term.present? || first_name.present? || last_name.present? || title.present? || category.present?
48
59
  end
49
60
 
50
61
  # Search and assigns the collection
51
62
  # Assigns the entire collection() if there are no search terms
52
63
  # Otherwise validate the search terms
53
64
  def search!
54
- @membership_owners = build_collection()
55
- @membership_owners = @membership_owners.none if present? && !valid?
56
- @membership_owners
65
+ @memberships = build_collection()
66
+ @memberships = @memberships.none if present? && !valid?
67
+ @memberships
57
68
  end
58
69
 
59
70
  # The unpaginated results of the search
60
- def membership_owners
61
- @membership_owners || collection
71
+ def memberships
72
+ @memberships || collection
62
73
  end
63
74
 
64
75
  # The paginated results
@@ -66,38 +77,53 @@ module EffectiveMembershipsDirectory
66
77
  page = (page || 1).to_i
67
78
  offset = [(page - 1), 0].max * per_page
68
79
 
69
- membership_owners.limit(per_page).offset(offset)
80
+ memberships.limit(per_page).offset(offset)
70
81
  end
71
82
 
72
83
  protected
73
84
 
74
85
  def build_collection
75
- owners = collection()
76
- raise('expected an ActiveRecord collection') unless owners.kind_of?(ActiveRecord::Relation)
77
- raise('expected a collection of membership_owners') unless owners.klass.respond_to?(:effective_memberships_owner?)
86
+ memberships = collection()
87
+ raise('expected an ActiveRecord collection') unless memberships.kind_of?(ActiveRecord::Relation)
88
+ raise('expected an ActiveRecord collection of Effective::Memberships') unless memberships.klass.respond_to?(:effective_membership?)
78
89
 
79
90
  # Filter by term
80
91
  if term.present?
81
- owners = Effective::Resource.new(owners).search_any(term, columns: search_any_columns)
92
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(term, columns: search_any_columns) }
93
+ memberships = memberships.where(owner: owners)
82
94
  end
83
95
 
84
96
  # Filter by first name
85
97
  if first_name.present?
86
- owners = Effective::Resource.new(owners).search_any(first_name, columns: :first_name)
98
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(first_name, columns: :first_name) }
99
+ memberships = memberships.where(owner: owners)
87
100
  end
88
101
 
89
102
  # Filter by last name
90
103
  if last_name.present?
91
- owners = Effective::Resource.new(owners).search_any(last_name, columns: :last_name)
104
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(last_name, columns: :last_name) }
105
+ memberships = memberships.where(owner: owners)
106
+ end
107
+
108
+ # Filter by title
109
+ if title.present?
110
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(last_name, columns: :title) }
111
+ memberships = memberships.where(owner: owners)
92
112
  end
93
113
 
94
114
  # Filter by category
95
115
  if category.present?
96
- cat = EffectiveMemberships.Category.where(id: category)
97
- owners = owners.members_with_category(cat) if cat.present?
116
+ memberships = memberships.with_category(EffectiveMemberships.Category.where(id: category))
98
117
  end
99
118
 
100
- owners
119
+ # Return an ActiveRecord::Relation of Effective::Memberships
120
+ memberships
121
+ end
122
+
123
+ private
124
+
125
+ def owner_klasses
126
+ Effective::Membership.owner_klasses
101
127
  end
102
128
 
103
129
  end
@@ -97,4 +97,8 @@ module EffectiveMembershipsOrganization
97
97
  representatives.reject(&:marked_for_destruction?).map(&:user)
98
98
  end
99
99
 
100
+ def membership_users
101
+ users.select { |user| user.is?(:member) && !user.archived? }
102
+ end
103
+
100
104
  end
@@ -1,6 +1,7 @@
1
1
  module Effective
2
2
  class Membership < ActiveRecord::Base
3
3
  belongs_to :owner, polymorphic: true
4
+ has_secure_token
4
5
 
5
6
  attr_accessor :current_action
6
7
 
@@ -24,30 +25,34 @@ module Effective
24
25
  fees_paid_period :date # The most recent period they have paid in. Start date of period.
25
26
  fees_paid_through_period :date # The most recent period they have paid in. End date of period. Kind of an expires.
26
27
 
28
+ # Membership Directory
29
+ owner_name :string
30
+ token :string
31
+
27
32
  timestamps
28
33
  end
29
34
 
30
35
  scope :deep, -> { includes(:owner, membership_categories: :category, membership_statuses: :status) }
31
- scope :sorted, -> { order(:id) }
36
+ scope :sorted, -> { order('lower(owner_name)') }
32
37
 
33
38
  scope :with_status, -> (statuses) {
34
- raise('expected an EffectiveMemberships.Status') unless Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
35
- where(id: MembershipStatus.where(status: statuses).select(:membership_id))
39
+ raise('expected an EffectiveMemberships.Status') unless statuses.class.respond_to?(:effective_memberships_status?) || Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
40
+ where(id: MembershipStatus.where(status_id: statuses).select(:membership_id))
36
41
  }
37
42
 
38
43
  scope :without_status, -> (statuses) {
39
- raise('expected an EffectiveMemberships.Status') unless Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
40
- where.not(id: MembershipStatus.where(status: statuses).select(:membership_id))
44
+ raise('expected an EffectiveMemberships.Status') unless statuses.class.respond_to?(:effective_memberships_status?) || Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
45
+ where.not(id: MembershipStatus.where(status_id: statuses).select(:membership_id))
41
46
  }
42
47
 
43
48
  scope :with_category, -> (categories) {
44
- raise('expected an EffectiveMemberships.Category') unless Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
45
- where(id: MembershipCategory.where(category: categories).select(:membership_id))
49
+ raise('expected an EffectiveMemberships.Category') unless categories.class.respond_to?(:effective_memberships_category?) || Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
50
+ where(id: MembershipCategory.where(category_id: categories).select(:membership_id))
46
51
  }
47
52
 
48
53
  scope :without_category, -> (categories) {
49
- raise('expected an EffectiveMemberships.Category') unless Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
50
- where.not(id: MembershipCategory.where(category: categories).select(:membership_id))
54
+ raise('expected an EffectiveMemberships.Category') unless categories.class.respond_to?(:effective_memberships_category?) || Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
55
+ where.not(id: MembershipCategory.where(category_id: categories).select(:membership_id))
51
56
  }
52
57
 
53
58
  scope :joined_before, -> (date) {
@@ -73,14 +78,24 @@ module Effective
73
78
  scope :not_in_good_standing, -> { with_status(EffectiveMemberships.Registrar.not_in_good_standing_status) }
74
79
  scope :in_good_standing, -> { without_status(EffectiveMemberships.Registrar.not_in_good_standing_status) }
75
80
 
81
+ scope :without_archived_owners, -> {
82
+ where.not(owner: klass.acts_as_archived_owner_klasses.map { |klass| klass.archived })
83
+ }
84
+
76
85
  before_validation do
77
86
  self.registration_on ||= joined_on
78
87
  end
79
88
 
89
+ before_validation(if: -> { owner.present? }) do
90
+ self.owner_name = owner.to_s
91
+ end
92
+
80
93
  before_validation(if: -> { number_changed? }) do
81
94
  self.number_as_integer = (number.present? ? (Integer(number) rescue nil) : nil)
82
95
  end
83
96
 
97
+ validates :owner_name, presence: true
98
+
84
99
  validates :number, uniqueness: { allow_blank: true }
85
100
  validates :number, presence: true, if: -> { categories.any?(:membership_number_required?) }
86
101
 
@@ -100,11 +115,19 @@ module Effective
100
115
  maximum('number_as_integer') || 0
101
116
  end
102
117
 
118
+ def self.effective_membership?
119
+ true
120
+ end
121
+
103
122
  def self.owner_klasses
104
123
  klasses = Effective::Membership.distinct(:owner_type).pluck(:owner_type)
105
124
  klasses.select { |klass| klass.safe_constantize }.map { |klass| klass.constantize }
106
125
  end
107
126
 
127
+ def self.acts_as_archived_owner_klasses
128
+ owner_klasses.select { |klass| klass.try(:acts_as_archived?) }
129
+ end
130
+
108
131
  def to_s
109
132
  return 'membership' if owner.blank?
110
133
 
@@ -1,11 +1,14 @@
1
1
  = effective_form_with(scope: :q, model: membership_directory, method: :get, url: request.path) do |f|
2
- - if f.object.term.present?
3
- = f.search_field :term, label: 'Name'
2
+ = f.search_field :term, label: 'Name'
4
3
 
5
- = f.search_field :first_name
6
- = f.search_field :last_name
4
+ -# Users only
5
+ /= f.search_field :first_name
6
+ /= f.search_field :last_name
7
7
 
8
- = f.select :category, EffectiveMemberships.Category.all
8
+ - # Organizations only
9
+ /= f.search_field :title
10
+
11
+ = f.select :category, membership_directory.categories
9
12
 
10
13
  = f.save('Search', class: 'btn btn-primary btn-search mr-3', name: nil)
11
14
  = link_to 'Reset filters', request.path
@@ -0,0 +1,20 @@
1
+ = card do
2
+ %h6= membership.owner
3
+ %p= membership.categories.map(&:membership_directory_title).to_sentence
4
+ %p= membership.statuses.map(&:membership_directory_title).to_sentence
5
+
6
+ - if membership.owner.try(:email).present?
7
+ %p= reveal_mail_to(membership.owner.email)
8
+
9
+ - if (organizations = membership.owner.try(:membership_organizations)).present?
10
+ .mb-4.membership-directory-organizations
11
+ - organizations.each do |organization|
12
+ %div= organization
13
+
14
+ - if (users = membership.owner.try(:membership_users)).present?
15
+ .mb-4.membership-directory-users
16
+ - users.each do |user|
17
+ %div= user
18
+
19
+ - if EffectiveResources.authorized?(self, :show, membership) && EffectiveResources.authorized?(self, :show, membership.owner)
20
+ = link_to 'Show more', effective_memberships.membership_directory_path(membership.token)
@@ -4,14 +4,14 @@
4
4
  - results = membership_directory.results(page: params[:page])
5
5
 
6
6
  - if membership_directory.present? && results.length == 0
7
- .alert.alert-info There are no results for your search. Please try again.
7
+ .mt-4.alert.alert-info There are no results for your search. Please try again.
8
8
 
9
9
  - results.in_groups_of(3).each do |group|
10
10
  .row.mt-4
11
- - group.each do |owner|
12
- - next unless owner
11
+ - group.each do |membership|
13
12
  .col-md
14
- = render('effective/membership_directory/membership_owner', membership: owner.membership, owner: owner)
13
+ - next unless membership
14
+ = render('effective/membership_directory/membership', membership: membership)
15
15
 
16
16
  %nav.d-flex.justify-content-center
17
17
  = bootstrap_paginate(results, per_page: membership_directory.per_page)
@@ -0,0 +1,25 @@
1
+ = render 'layout' do
2
+ .effective-membership
3
+
4
+ %h6= @membership.owner
5
+ %p= @membership.categories.map(&:membership_directory_title).to_sentence
6
+ %p= @membership.statuses.map(&:membership_directory_title).to_sentence
7
+
8
+ - if @membership.owner.respond_to?(:rich_text_body)
9
+ .mb-4= @membership.owner.rich_text_body.to_s
10
+
11
+ - if @membership.owner.try(:email).present?
12
+ %p= reveal_mail_to(@membership.owner.email)
13
+
14
+ - if (organizations = @membership.owner.try(:membership_organizations)).present?
15
+ .mb-4.membership-directory-organizations
16
+ - organizations.each do |organization|
17
+ %div= organization
18
+
19
+ - if (users = @membership.owner.try(:membership_users)).present?
20
+ .mb-4.membership-directory-users
21
+ - users.each do |user|
22
+ %div= user
23
+
24
+ %hr
25
+ = link_to 'Return to Directory', effective_memberships.membership_directory_index_path, class: 'btn btn-primary'
data/config/routes.rb CHANGED
@@ -26,7 +26,7 @@ EffectiveMemberships::Engine.routes.draw do
26
26
  resources :build, controller: :fee_payments, only: [:show, :update]
27
27
  end
28
28
 
29
- resources :membership_directory, only: :index
29
+ resources :membership_directory, only: [:index, :show]
30
30
  get '/directory', to: 'membership_directory#index'
31
31
 
32
32
  resources :membership_cards, only: :index
@@ -95,6 +95,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
95
95
  t.date :fees_paid_period
96
96
  t.date :fees_paid_through_period
97
97
 
98
+ t.string :owner_name
99
+ t.string :token
100
+
98
101
  t.datetime :updated_at
99
102
  t.datetime :created_at
100
103
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.9.7'
2
+ VERSION = '0.9.8'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_memberships
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
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: 2022-12-01 00:00:00.000000000 Z
11
+ date: 2022-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -483,9 +483,10 @@ files:
483
483
  - app/views/effective/membership_cards/index.html.haml
484
484
  - app/views/effective/membership_directory/_form.html.haml
485
485
  - app/views/effective/membership_directory/_layout.html.haml
486
+ - app/views/effective/membership_directory/_membership.html.haml
486
487
  - app/views/effective/membership_directory/_membership_directory.html.haml
487
- - app/views/effective/membership_directory/_membership_owner.html.haml
488
488
  - app/views/effective/membership_directory/index.html.haml
489
+ - app/views/effective/membership_directory/show.html.haml
489
490
  - app/views/effective/memberships/_dashboard.html.haml
490
491
  - app/views/effective/memberships/_membership.html.haml
491
492
  - app/views/effective/memberships_mailer/applicant_approved.liquid
@@ -1,7 +0,0 @@
1
- = card do
2
- %h6= owner
3
- %p= membership.categories.map(&:membership_directory_title).to_sentence
4
- %p= membership.statuses.map(&:membership_directory_title).to_sentence
5
-
6
- - if owner.try(:email).present?
7
- %p= reveal_mail_to(owner.email)