effective_resources 1.17.2 → 1.18.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: 88760067301847f6d36a2f8550224e019acf06cc9fcc9021a7cf22799e09d560
4
- data.tar.gz: 8a922371e95e9f9c91e1cd907b858f19316615508a05077ec5025c7c82c4e1c4
3
+ metadata.gz: '0823eab342743da2a61c1b174cad39ffc77c6602c8422488bd32c113148b066f'
4
+ data.tar.gz: 3958c07bc7d38c1c3de867e699b899fddc1833e029b7b639635a08b9a92b9bdc
5
5
  SHA512:
6
- metadata.gz: c19cbb3988ce98384ff670148617f5779337254fcaee5b4c68f354cd0d9a2bc40d15497db83c53d3f5dd9c37a9e13191f40bf3ed435a8607b05963e2678a292b
7
- data.tar.gz: 96e9c5059d55ff3ad40a10f891fd8765eb9fee9d359d19809b1566a47dca26cbccde1f18e4f182f64740c2738134d6e08d93be7170add23ef917bed1631c7a9e
6
+ metadata.gz: 180567d91706dee43b3ae5ab9e09e9f1abe0f1f352daa1bbf69ed3110564814ddacbc542d8293d5df8093dc94a36d8547a6f4814e307b6966f5ca7e49e7a34a9
7
+ data.tar.gz: 9852aac45f8341b0e27509d1b82c59f5d739eb3d1194daad74f6f1c1a4e7a29a0705a90dedd15945fa2af14c6cc546429d6f07db559d8785b182fa0a6a2d0c3b
data/README.md CHANGED
@@ -354,6 +354,31 @@ You can also call `render_wizard_sidebar(resource)` without the block syntax.
354
354
 
355
355
  If you add `f.hidden_field(:skip_to_step, value: 'stepc')` you can control the next step.
356
356
 
357
+ ## Select2 Ajax Controller
358
+
359
+ This gem provides an admin endpoint for select2 AJAX to fetch users.
360
+
361
+ To use this endpoint please add
362
+
363
+ ```
364
+ can :admin, :effective_resources
365
+ ```
366
+
367
+ And then create a select field like this:
368
+
369
+ ```
370
+ = f.select :user_id, current_user.class.all,
371
+ ajax_url: effective_resources.users_admin_select2_ajax_index_path
372
+ ```
373
+
374
+ To format the results, add a method to your User class. It can return html.
375
+
376
+ ```
377
+ def to_select2
378
+ "<span>#{user.first_name} #{user.last_name}</span> <small>#{user.email}</small>"
379
+ end
380
+ ```
381
+
357
382
  ## Testing
358
383
 
359
384
  Run tests by:
@@ -0,0 +1,24 @@
1
+ module Admin
2
+ class Select2AjaxController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+ before_action { EffectiveResources.authorize!(self, :admin, :effective_resources) }
5
+
6
+ include Effective::Select2AjaxController
7
+
8
+ def users
9
+ collection = current_user.class.all
10
+
11
+ respond_with_select2_ajax(collection) do |user|
12
+ { id: user.to_param, text: user.try(:to_select2) || to_select2(user) }
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def to_select2(user)
19
+ "<span>#{user.first_name} #{user.last_name}</span> <small>#{user.email}</small>"
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -60,7 +60,9 @@ module Effective
60
60
  when ActiveRecord::StaleObjectError
61
61
  flash.now[:danger] = "#{flash.now[:danger]} <a href='#', class='alert-link' onclick='window.location.reload(true); return false;'>reload page and try again</a>"
62
62
  raise(ActiveRecord::Rollback) # This is a soft error, we want to display the flash message to user
63
- when Effective::ActionFailed, ActiveRecord::RecordInvalid, RuntimeError
63
+ when Effective::ActionFailed
64
+ # Nothing to do
65
+ when ActiveRecord::RecordInvalid, RuntimeError
64
66
  raise(ActiveRecord::Rollback) # This is a soft error, we want to display the flash message to user
65
67
  else
66
68
  raise(e) # This is a real error that should be sent to 500. Client should not see the message.
@@ -0,0 +1,52 @@
1
+ module Effective
2
+ module Select2AjaxController
3
+ extend ActiveSupport::Concern
4
+
5
+ def respond_with_select2_ajax(collection, skip_search: false, &block)
6
+ raise('collection should be an ActiveRecord::Relation') unless collection.kind_of?(ActiveRecord::Relation)
7
+
8
+ # Authorize
9
+ EffectiveResources.authorize!(self, :index, collection.klass)
10
+
11
+ # Scope
12
+ if collection.respond_to?(:select2_ajax)
13
+ collection = collection.select2_ajax
14
+ elsif collection.respond_to?(:sorted)
15
+ collection = collection.sorted
16
+ end
17
+
18
+ # Search
19
+ if (term = params[:term]).present? && !skip_search
20
+ collection = Effective::Resource.new(collection).search_any(term)
21
+ end
22
+
23
+ # Paginate
24
+ per_page = 50
25
+ page = (params[:page] || 1).to_i
26
+ last = (collection.reselect(:id).count.to_f / per_page).ceil
27
+ more = page < last
28
+
29
+ offset = [(page - 1), 0].max * per_page
30
+ collection = collection.limit(per_page).offset(offset)
31
+
32
+ # Results
33
+ results = collection.map do |resource|
34
+ if block_given?
35
+ option = yield(resource)
36
+ raise('expected a Hash with id and text params') unless option.kind_of?(Hash) && option[:id] && option[:text]
37
+ option
38
+ else
39
+ { id: resource.to_param, text: resource.try(:to_select2) || resource.to_s }
40
+ end
41
+ end
42
+
43
+ # Respond
44
+ respond_to do |format|
45
+ format.js do
46
+ render json: { results: results, pagination: { more: more } }
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -207,6 +207,20 @@ module EffectiveResourcesHelper
207
207
  end
208
208
  alias_method :render_resource, :render_resource_partial
209
209
 
210
+ def render_if_exists(partial, atts = {})
211
+ raise('expected a path') unless partial.kind_of?(String)
212
+ raise('path should not include spaces') if partial.include?(' ')
213
+
214
+ pieces = partial.to_s.split('/') - [nil, '']
215
+
216
+ file = pieces.last
217
+ path = pieces[0..-2].join('/')
218
+
219
+ if lookup_context.exists?(file, [path], :partial)
220
+ render(partial, atts)
221
+ end
222
+ end
223
+
210
224
  # Tableize attributes
211
225
  # This is used by effective_orders, effective_logging, effective_trash and effective_mergery
212
226
  def tableize_hash(obj, table: 'table', th: true, sub_table: 'table', sub_th: true, flatten: true)
@@ -248,4 +262,32 @@ module EffectiveResourcesHelper
248
262
  controller.class.try(:effective_wizard_controller?) && defined?(resource) && resource.draft?
249
263
  end
250
264
 
265
+ def wizard_card(resource, &block)
266
+ raise('expected a block') unless block_given?
267
+ raise('expected an acts_as_wizard resource') unless resource.class.respond_to?(:acts_as_wizard?)
268
+
269
+ step = resource.render_step
270
+ raise('expected a render_step') unless step.present?
271
+
272
+ title = resource.wizard_step_title(step)
273
+ raise("expected a title for step #{step}") unless title.present?
274
+
275
+ link = if edit_effective_wizard? && resource.can_visit_step?(step)
276
+ link_to('Edit', wizard_path(step), title: "Edit #{title}")
277
+ end
278
+
279
+ content_tag(:div, class: 'card') do
280
+ content_tag(:div, class: 'card-body yo') do
281
+ content_tag(:div, class: 'row') do
282
+ content_tag(:div, class: 'col-sm') do
283
+ content_tag(:h5, title, class: 'card-title')
284
+ end +
285
+ content_tag(:div, class: 'col-sm-auto text-right') do
286
+ (link || '')
287
+ end
288
+ end + capture(&block)
289
+ end
290
+ end
291
+ end
292
+
251
293
  end
@@ -29,6 +29,9 @@ module ActsAsWizard
29
29
 
30
30
  attr_accessor :current_user
31
31
 
32
+ # Used by the view when rendering each partial. Not the current step.
33
+ attr_accessor :render_step
34
+
32
35
  if Rails.env.test? # So our tests can override the required_steps method
33
36
  cattr_accessor :test_required_steps
34
37
  end
@@ -6,6 +6,10 @@ module Effective
6
6
  TARGET_LIST_LIMIT = 1500
7
7
  TARGET_KEYS_LIMIT = 30000
8
8
 
9
+ DO_NOT_SEARCH_EQUALS = ['unconfirmed_email', 'provider', 'secret', 'crypt', 'salt', 'uid', 'certificate', 'otp', 'ssn']
10
+ DO_NOT_SEARCH_INCLUDE = ['password']
11
+ DO_NOT_SEARCH_END_WITH = ['_url', '_param', '_token', '_type', '_id', '_key', '_ip']
12
+
9
13
  # This could be active_model? in which we just return the klass itself here
10
14
  # This value ends up being crud_controller resource_scope()
11
15
  def relation
@@ -197,18 +201,31 @@ module Effective
197
201
  end
198
202
 
199
203
  # Otherwise, we fall back to a string/text search of all columns
200
- columns = Array(columns || search_columns)
204
+ columns = Array(columns || search_columns).reject do |column|
205
+ DO_NOT_SEARCH_EQUALS.any? { |value| column == value } ||
206
+ DO_NOT_SEARCH_INCLUDE.any? { |value| column.include?(value) } ||
207
+ DO_NOT_SEARCH_END_WITH.any? { |value| column.end_with?(value) }
208
+ end
209
+
201
210
  fuzzy = true unless fuzzy == false
202
211
 
203
- conditions = (
204
- if fuzzy
205
- columns.map { |name| "#{sql_column(name)} #{ilike} :fuzzy" }
206
- else
207
- columns.map { |name| "#{sql_column(name)} = :value" }
208
- end
209
- ).join(' OR ')
212
+ # Retval
213
+ searched = relation
214
+ terms = value.split(' ') - [nil, '']
215
+
216
+ terms.each do |term|
217
+ conditions = (
218
+ if fuzzy
219
+ columns.map { |name| "#{sql_column(name)} #{ilike} :fuzzy" }
220
+ else
221
+ columns.map { |name| "#{sql_column(name)} = :term" }
222
+ end
223
+ ).join(' OR ')
224
+
225
+ searched = searched.where(conditions, fuzzy: "%#{term}%", term: term)
226
+ end
210
227
 
211
- relation.where(conditions, fuzzy: "%#{value}%", value: value)
228
+ searched
212
229
  end
213
230
 
214
231
  private
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ Rails.application.routes.draw do
2
+ mount EffectiveResources::Engine => '/', as: 'effective_resources'
3
+ end
4
+
5
+ EffectiveResources::Engine.routes.draw do
6
+
7
+ namespace :admin do
8
+ resources :select2_ajax, only: [] do
9
+ get :users, on: :collection
10
+ end
11
+ end
12
+
13
+ end
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '1.17.2'.freeze
2
+ VERSION = '1.18.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.17.2
4
+ version: 1.18.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-05-25 00:00:00.000000000 Z
11
+ date: 2022-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -133,6 +133,7 @@ files:
133
133
  - README.md
134
134
  - app/assets/javascripts/effective_resources.js
135
135
  - app/assets/javascripts/effective_resources/effective_ujs.js
136
+ - app/controllers/admin/select2_ajax_controller.rb
136
137
  - app/controllers/concerns/effective/crud_controller.rb
137
138
  - app/controllers/concerns/effective/crud_controller/actions.rb
138
139
  - app/controllers/concerns/effective/crud_controller/dsl.rb
@@ -142,6 +143,7 @@ files:
142
143
  - app/controllers/concerns/effective/crud_controller/save.rb
143
144
  - app/controllers/concerns/effective/crud_controller/submits.rb
144
145
  - app/controllers/concerns/effective/flash_messages.rb
146
+ - app/controllers/concerns/effective/select2_ajax_controller.rb
145
147
  - app/controllers/concerns/effective/wizard_controller.rb
146
148
  - app/controllers/concerns/effective/wizard_controller/actions.rb
147
149
  - app/controllers/concerns/effective/wizard_controller/before_actions.rb
@@ -206,6 +208,7 @@ files:
206
208
  - app/views/effective/resource/_actions_glyphicons.html.haml
207
209
  - app/views/layouts/effective_mailer_layout.html.haml
208
210
  - config/effective_resources.rb
211
+ - config/routes.rb
209
212
  - lib/effective_resources.rb
210
213
  - lib/effective_resources/effective_gem.rb
211
214
  - lib/effective_resources/engine.rb