effective_memberships 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5088dfc90ed9a12111011d7f9c8b639553abf0b03af9eea5a197c80d3b5c97f9
4
- data.tar.gz: cbedc16b06e69feac3e1921c8963d0d1e2bb3f44b4efeb4aabab0682efe582c4
3
+ metadata.gz: 0a2ae153f152ca4d2295c8847e7848d10dde99d015c77367606cc1d00feb8743
4
+ data.tar.gz: f41d582a3c5da8491cfb82ac7129aaa796c3f4fc14ee49e5eff6e2770d725200
5
5
  SHA512:
6
- metadata.gz: 8ebdebc9b7673481c1d49cca98ad7a8ead414296783dcf886e0ebdd5edec24a75f71c88d1698748b4035cfec97b14029c186c9d8e7277c6065404e3f5c837f15
7
- data.tar.gz: 3ed063f4063d1c40187b4366163dd349a4087a25e18b4083aa781ecc4b7d003c5022e1eae5db0854066ce4d48f3b3b0ba4cedbb7d21a9f3598977fc2e770c6dd
6
+ metadata.gz: 218f5706b65bfc70fa9cd458678fb24cfa106751f91c98a636e304dc66494879789e95bcccfebf79eb993dd7797b56b72cf640de69013ded6b117e2ca6fb0f64
7
+ data.tar.gz: 2fcba0dab68d21ce5653e9d9e227895e227d887c3fbc80c2533be72cd190b1ad6a8a02b7b7041692957cd4edca505d24533fcb8653c82c3ace37623122d4498a
@@ -0,0 +1,36 @@
1
+ module Effective
2
+ class MembershipDirectoryController < ApplicationController
3
+ include Effective::CrudController
4
+
5
+ def index
6
+ @page_title = 'Directory'
7
+ EffectiveResources.authorize!(self, :index, Effective::Membership)
8
+
9
+ # Sometimes we just display a Datatable for the membership directory
10
+ @datatable = EffectiveResources.best('EffectiveMembershipsDirectoryDatatable').new
11
+
12
+ # But more often we do a full membership directory search screen
13
+ @membership_directory = build_membership_directory
14
+ @membership_directory.search!
15
+
16
+ @memberships = @membership_directory.results(page: params[:page])
17
+ end
18
+
19
+ def build_membership_directory
20
+ directory = EffectiveMemberships.MembershipDirectory.new(search_params)
21
+ directory.current_user = current_user
22
+ directory
23
+ end
24
+
25
+ def search_params
26
+ return {} unless params[:q].present?
27
+
28
+ if params[:q].respond_to?(:to_h) # From the search form
29
+ params.require(:q).permit!
30
+ else
31
+ { term: params.permit(:q).fetch(:q) } # From the url /directory?q=asdf
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -11,7 +11,7 @@ class EffectiveMembershipsDirectoryDatatable < Effective::Datatable
11
11
  end
12
12
 
13
13
  collection do
14
- scope = Effective::Membership.deep.good_standing.includes(:owner)
14
+ scope = Effective::Membership.directory.all
15
15
 
16
16
  archived_klasses.each do |klass|
17
17
  scope = scope.where.not(owner_id: klass.archived.select('id'), owner_type: klass.name)
@@ -21,11 +21,7 @@ class EffectiveMembershipsDirectoryDatatable < Effective::Datatable
21
21
  end
22
22
 
23
23
  def archived_klasses
24
- @archived_klasses ||= begin
25
- klasses = Effective::Membership.distinct(:owner_type).pluck(:owner_type)
26
- klasses = klasses.select { |klass| klass.safe_constantize.try(:acts_as_archived?) }
27
- klasses.map { |klass| klass.constantize }
28
- end
24
+ @archived_klasses ||= Effective::Membership.owner_klasses.select { |klass| klass.try(:acts_as_archived?) }
29
25
  end
30
26
 
31
27
  end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is a search model for the MembershipDirectories screen
4
+ #
5
+ # EffectiveMembershipsDirectory
6
+ # Mark your directory search model with include EffectiveMembershipsDirectory
7
+
8
+ module EffectiveMembershipsDirectory
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+ def effective_memberships_directory?; true; end
13
+ end
14
+
15
+ included do
16
+ include ActiveModel::Model
17
+
18
+ attr_accessor :current_user
19
+ attr_accessor :term
20
+ attr_accessor :category
21
+
22
+ attr_accessor :first_name
23
+ attr_accessor :last_name
24
+
25
+ validates :term, length: { minimum: 3, allow_blank: true }
26
+ validates :first_name, length: { minimum: 2, allow_blank: true }
27
+ validates :last_name, length: { minimum: 2, allow_blank: true }
28
+ end
29
+
30
+ # Base collection to search. Can be configured per tenant.
31
+ def collection
32
+ Effective::Membership.directory
33
+ end
34
+
35
+ # Search Users and Organizations for only these fields. Passed into search_any. Return nil for all.
36
+ # Should this include email?
37
+ def search_any_columns
38
+ [:title, :name, :first_name, :middle_name, :last_name]
39
+ end
40
+
41
+ def per_page
42
+ 24
43
+ end
44
+
45
+ def present?
46
+ term.present? || first_name.present? || last_name.present? || category.present?
47
+ end
48
+
49
+ # Search and assigns the collection
50
+ # Assigns the entire collection() if there are no search terms
51
+ # Otherwise validate the search terms
52
+ def search!
53
+ @memberships = build_collection()
54
+ @memberships = @memberships.none if present? && !valid?
55
+ @memberships
56
+ end
57
+
58
+ # The unpaginated results of the search
59
+ def memberships
60
+ @memberships || collection
61
+ end
62
+
63
+ # The paginated results
64
+ def results(page: nil)
65
+ page = (page || 1).to_i
66
+ offset = [(page - 1), 0].max * per_page
67
+
68
+ memberships().limit(per_page).offset(offset)
69
+ end
70
+
71
+ protected
72
+
73
+ def build_collection
74
+ memberships = collection()
75
+ raise('expected an ActiveRecord collection') unless memberships.kind_of?(ActiveRecord::Relation)
76
+
77
+ # Filter by term
78
+ if term.present?
79
+ memberships = search_owners(memberships, term, search_any_columns)
80
+ end
81
+
82
+ # Filter by first name
83
+ if first_name.present?
84
+ memberships = search_owners(memberships, first_name, :first_name)
85
+ end
86
+
87
+ # Filter by last name
88
+ if last_name.present?
89
+ memberships = search_owners(memberships, last_name, :last_name)
90
+ end
91
+
92
+ # Filter by category
93
+ if category.present?
94
+ cat = EffectiveMemberships.Category.where(id: category)
95
+ memberships = memberships.with_category(cat) if cat.present?
96
+ end
97
+
98
+ memberships
99
+ end
100
+
101
+ def search_owners(collection, term, columns = nil)
102
+ results = collection.none()
103
+
104
+ owner_klasses.each do |klass|
105
+ search = Effective::Resource.new(klass).search_any(term, columns: columns)
106
+ searched = collection.where(owner_type: klass.name, owner_id: search.select('id'))
107
+
108
+ results = results.or(searched)
109
+ end
110
+
111
+ collection.merge(results)
112
+ end
113
+
114
+ def owner_klasses
115
+ @owner_klasses ||= Effective::Membership.owner_klasses
116
+ end
117
+
118
+ end
@@ -7,12 +7,9 @@
7
7
  module EffectiveMembershipsOwner
8
8
  extend ActiveSupport::Concern
9
9
 
10
- mattr_accessor :descendants
11
-
12
10
  module Base
13
11
  def effective_memberships_owner
14
12
  include ::EffectiveMembershipsOwner
15
- (EffectiveMembershipsOwner.descendants ||= []) << self
16
13
  end
17
14
  end
18
15
 
@@ -27,7 +27,7 @@ module Effective
27
27
  timestamps
28
28
  end
29
29
 
30
- scope :deep, -> { includes(membership_categories: :category) }
30
+ scope :deep, -> { includes(:owner, membership_categories: :category) }
31
31
  scope :sorted, -> { order(:id) }
32
32
 
33
33
  scope :with_status, -> (statuses) {
@@ -73,6 +73,8 @@ module Effective
73
73
  scope :not_in_good_standing, -> { with_status(EffectiveMemberships.Registrar.not_in_good_standing_status) }
74
74
  scope :in_good_standing, -> { without_status(EffectiveMemberships.Registrar.not_in_good_standing_status) }
75
75
 
76
+ scope :directory, -> { deep.in_good_standing.order(:id) }
77
+
76
78
  before_validation do
77
79
  self.registration_on ||= joined_on
78
80
  end
@@ -100,6 +102,11 @@ module Effective
100
102
  maximum('number_as_integer') || 0
101
103
  end
102
104
 
105
+ def self.owner_klasses
106
+ klasses = Effective::Membership.distinct(:owner_type).pluck(:owner_type)
107
+ klasses.select { |klass| klass.safe_constantize }.map { |klass| klass.constantize }
108
+ end
109
+
103
110
  def to_s
104
111
  return 'membership' if owner.blank?
105
112
 
@@ -0,0 +1,5 @@
1
+ module Effective
2
+ class MembershipDirectory
3
+ include EffectiveMembershipsDirectory
4
+ end
5
+ end
@@ -4,7 +4,7 @@
4
4
  = f.hidden_field :owner_type
5
5
  - else
6
6
  - raise('todo')
7
- - collection = EffectiveMembershipsOwner.descendants.map { |d| [d.name.to_s, d.members.sorted] }.to_h
7
+ /- collection = EffectiveMembershipsOwner.descendants.map { |d| [d.name.to_s, d.members.sorted] }.to_h
8
8
  = f.select :owner_id, collection, polymorphic: true
9
9
 
10
10
  = f.date_field :start_on, hint: 'The start date of this period in history. Must be present.'
@@ -0,0 +1,11 @@
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'
4
+
5
+ = f.search_field :first_name
6
+ = f.search_field :last_name
7
+
8
+ = f.select :category, EffectiveMemberships.Category.all
9
+
10
+ = f.save('Search', class: 'btn btn-primary btn-search mr-3', name: nil)
11
+ = link_to 'Reset filters', request.path
@@ -0,0 +1,2 @@
1
+ .effective-membership-directory
2
+ = yield
@@ -0,0 +1,4 @@
1
+ = card do
2
+ %h6= membership.owner
3
+ %p= membership.categories.to_sentence
4
+ %p= membership.statuses.to_sentence
@@ -0,0 +1,16 @@
1
+ = render 'layout' do
2
+ = render('effective/membership_directory/form', membership_directory: membership_directory)
3
+
4
+ - results = membership_directory.results(page: params[:page])
5
+
6
+ - if membership_directory.present? && results.length == 0
7
+ .alert.alert-info There are no results for your search. Please try again.
8
+
9
+ - results.in_groups_of(3).each do |group|
10
+ .row.mt-4
11
+ - group.each do |membership|
12
+ - next unless membership
13
+ .col-md= render('effective/membership_directory/membership', membership: membership)
14
+
15
+ %nav.d-flex.justify-content-center
16
+ = bootstrap_paginate(results, per_page: membership_directory.per_page)
@@ -0,0 +1,2 @@
1
+ /= render_datatable(@datatable, buttons: false)
2
+ = render('effective/membership_directory/membership_directory', membership_directory: @membership_directory)
@@ -20,6 +20,7 @@ EffectiveMemberships.setup do |config|
20
20
  # config.applicant_review_class_name = 'Effective::ApplicantReview'
21
21
  # config.fee_payment_class_name = 'Effective::FeePayment'
22
22
  # config.membership_card_class_name = 'Effective::MembershipCard'
23
+ # config.membership_directory_class_name = 'Effective::MembershipDirectory'
23
24
  # config.registrar_class_name = 'Effective::Registrar'
24
25
  # config.organization_class_name = 'Effective::Organization'
25
26
  # config.status_class_name = 'Effective::Status'
data/config/routes.rb CHANGED
@@ -26,7 +26,8 @@ EffectiveMemberships::Engine.routes.draw do
26
26
  resources :build, controller: :fee_payments, only: [:show, :update]
27
27
  end
28
28
 
29
- get '/directory', to: 'memberships_directory#index'
29
+ resources :membership_directory, only: :index
30
+ get '/directory', to: 'membership_directory#index'
30
31
 
31
32
  resources :membership_cards, only: :index
32
33
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.8.0'
2
+ VERSION = '0.8.1'
3
3
  end
@@ -7,7 +7,7 @@ module EffectiveMemberships
7
7
  def self.config_keys
8
8
  [
9
9
  :categories_table_name, :applicants_table_name, :applicant_reviews_table_name, :fee_payments_table_name, :organizations_table_name, :representatives_table_name, :statuses_table_name,
10
- :category_class_name, :organization_class_name, :applicant_class_name, :applicant_review_class_name, :fee_payment_class_name, :registrar_class_name, :membership_card_class_name, :status_class_name,
10
+ :category_class_name, :organization_class_name, :applicant_class_name, :applicant_review_class_name, :fee_payment_class_name, :registrar_class_name, :membership_card_class_name, :membership_directory_class_name, :status_class_name,
11
11
  :additional_fee_types, :applicant_reviews, :applicant_endorsements_endorser_collection,
12
12
  :layout,
13
13
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates
@@ -40,6 +40,10 @@ module EffectiveMemberships
40
40
  membership_card_class_name&.constantize || Effective::MembershipCard
41
41
  end
42
42
 
43
+ def self.MembershipDirectory
44
+ membership_directory_class_name&.constantize || Effective::MembershipDirectory
45
+ end
46
+
43
47
  def self.Status
44
48
  status_class_name&.constantize || Effective::Status
45
49
  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.8.0
4
+ version: 0.8.1
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-10-20 00:00:00.000000000 Z
11
+ date: 2022-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -275,7 +275,7 @@ files:
275
275
  - app/controllers/effective/applicants_controller.rb
276
276
  - app/controllers/effective/fee_payments_controller.rb
277
277
  - app/controllers/effective/membership_cards_controller.rb
278
- - app/controllers/effective/memberships_directory_controller.rb
278
+ - app/controllers/effective/membership_directory_controller.rb
279
279
  - app/controllers/effective/organizations_controller.rb
280
280
  - app/controllers/effective/representatives_controller.rb
281
281
  - app/datatables/admin/effective_applicant_course_areas_datatable.rb
@@ -312,6 +312,7 @@ files:
312
312
  - app/models/concerns/effective_memberships_applicant_review.rb
313
313
  - app/models/concerns/effective_memberships_card.rb
314
314
  - app/models/concerns/effective_memberships_category.rb
315
+ - app/models/concerns/effective_memberships_directory.rb
315
316
  - app/models/concerns/effective_memberships_fee_payment.rb
316
317
  - app/models/concerns/effective_memberships_organization.rb
317
318
  - app/models/concerns/effective_memberships_owner.rb
@@ -334,6 +335,7 @@ files:
334
335
  - app/models/effective/membership.rb
335
336
  - app/models/effective/membership_card.rb
336
337
  - app/models/effective/membership_category.rb
338
+ - app/models/effective/membership_directory.rb
337
339
  - app/models/effective/membership_history.rb
338
340
  - app/models/effective/membership_status.rb
339
341
  - app/models/effective/organization.rb
@@ -477,9 +479,13 @@ files:
477
479
  - app/views/effective/fees/_dashboard.html.haml
478
480
  - app/views/effective/fees/_fee.html.haml
479
481
  - app/views/effective/membership_cards/index.html.haml
482
+ - app/views/effective/membership_directory/_form.html.haml
483
+ - app/views/effective/membership_directory/_layout.html.haml
484
+ - app/views/effective/membership_directory/_membership.html.haml
485
+ - app/views/effective/membership_directory/_membership_directory.html.haml
486
+ - app/views/effective/membership_directory/index.html.haml
480
487
  - app/views/effective/memberships/_dashboard.html.haml
481
488
  - app/views/effective/memberships/_membership.html.haml
482
- - app/views/effective/memberships_directory/index.html.haml
483
489
  - app/views/effective/memberships_mailer/applicant_approved.liquid
484
490
  - app/views/effective/memberships_mailer/applicant_completed.liquid
485
491
  - app/views/effective/memberships_mailer/applicant_declined.liquid
@@ -1,14 +0,0 @@
1
- module Effective
2
- class MembershipsDirectoryController < ApplicationController
3
- include Effective::CrudController
4
-
5
- def index
6
- @page_title = 'Directory'
7
-
8
- EffectiveResources.authorize!(self, :index, Effective::Membership)
9
-
10
- @datatable = EffectiveResources.best('EffectiveMembershipsDirectoryDatatable').new
11
- end
12
-
13
- end
14
- end
@@ -1 +0,0 @@
1
- = render_datatable(@datatable, buttons: false)