effective_memberships 0.8.0 → 0.8.2

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: d55b0a5c31e8f259614c649af1fe89e2d36cb412652dc6d5ac96f051a925a7ee
4
+ data.tar.gz: 3850e9a4d2ba175becb4e0f487bc041c726516d9462470ee6c464a19ece0d559
5
5
  SHA512:
6
- metadata.gz: 8ebdebc9b7673481c1d49cca98ad7a8ead414296783dcf886e0ebdd5edec24a75f71c88d1698748b4035cfec97b14029c186c9d8e7277c6065404e3f5c837f15
7
- data.tar.gz: 3ed063f4063d1c40187b4366163dd349a4087a25e18b4083aa781ecc4b7d003c5022e1eae5db0854066ce4d48f3b3b0ba4cedbb7d21a9f3598977fc2e770c6dd
6
+ metadata.gz: d6b197509eb8ce44fd7b15230c8b55171eccf2b017017f6e38eb45917453abf96a210118fd25df35d962cf448efc3625db45f1dafe720da32c18d1ee68ab7569
7
+ data.tar.gz: 7c2e9ecd43439c7abf4a174ef1adae97938704a941e8338225b3905b38fb0e7d10aae5d075ce169b1140b77f193dc055349751569524163d5a301d65801848cf
@@ -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,103 @@
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
+ # Example::User.members.membership_in_good_standing.all
33
+ raise('to be implemented by app membership_directory')
34
+ end
35
+
36
+ # Search Users and Organizations for only these fields. Passed into search_any. Return nil for all.
37
+ # Should this include email?
38
+ def search_any_columns
39
+ [:title, :name, :first_name, :middle_name, :last_name]
40
+ end
41
+
42
+ def per_page
43
+ 24
44
+ end
45
+
46
+ def present?
47
+ term.present? || first_name.present? || last_name.present? || category.present?
48
+ end
49
+
50
+ # Search and assigns the collection
51
+ # Assigns the entire collection() if there are no search terms
52
+ # Otherwise validate the search terms
53
+ def search!
54
+ @membership_owners = build_collection()
55
+ @membership_owners = @membership_owners.none if present? && !valid?
56
+ @membership_owners
57
+ end
58
+
59
+ # The unpaginated results of the search
60
+ def membership_owners
61
+ @membership_owners || collection
62
+ end
63
+
64
+ # The paginated results
65
+ def results(page: nil)
66
+ page = (page || 1).to_i
67
+ offset = [(page - 1), 0].max * per_page
68
+
69
+ membership_owners.limit(per_page).offset(offset)
70
+ end
71
+
72
+ protected
73
+
74
+ 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?)
78
+
79
+ # Filter by term
80
+ if term.present?
81
+ owners = Effective::Resource.new(owners).search_any(term, columns: search_any_columns)
82
+ end
83
+
84
+ # Filter by first name
85
+ if first_name.present?
86
+ owners = Effective::Resource.new(owners).search_any(first_name, columns: :first_name)
87
+ end
88
+
89
+ # Filter by last name
90
+ if last_name.present?
91
+ owners = Effective::Resource.new(owners).search_any(last_name, columns: :last_name)
92
+ end
93
+
94
+ # Filter by category
95
+ if category.present?
96
+ cat = EffectiveMemberships.Category.where(id: category)
97
+ owners = owners.members_with_category(cat) if cat.present?
98
+ end
99
+
100
+ owners
101
+ end
102
+
103
+ 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) {
@@ -100,6 +100,11 @@ module Effective
100
100
  maximum('number_as_integer') || 0
101
101
  end
102
102
 
103
+ def self.owner_klasses
104
+ klasses = Effective::Membership.distinct(:owner_type).pluck(:owner_type)
105
+ klasses.select { |klass| klass.safe_constantize }.map { |klass| klass.constantize }
106
+ end
107
+
103
108
  def to_s
104
109
  return 'membership' if owner.blank?
105
110
 
@@ -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,17 @@
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 |owner|
12
+ - next unless owner
13
+ .col-md
14
+ = render('effective/membership_directory/membership_owner', membership: owner.membership, owner: owner)
15
+
16
+ %nav.d-flex.justify-content-center
17
+ = bootstrap_paginate(results, per_page: membership_directory.per_page)
@@ -0,0 +1,4 @@
1
+ = card do
2
+ %h6= owner
3
+ %p= membership.categories.to_sentence
4
+ %p= membership.statuses.to_sentence
@@ -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.2'
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.2
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_directory.html.haml
485
+ - app/views/effective/membership_directory/_membership_owner.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)