trk_datatables 0.2.8 → 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bbcc94c87611e1aaa08588c6599df2c691192850905da3b981a69d908ffb981
4
- data.tar.gz: ac998b4e62500caf9be81419909a8c1d530f64c7737330c0fd4de22a40a082df
3
+ metadata.gz: dfebccd40ad802ae6e7e6beb1eebec9099f9ede5bf4ed4d2f6f9ed92a08a8f03
4
+ data.tar.gz: 0fcb0efd54b898d2d2aa68ff76c095293fa0b57abb48a37bd893aa59a676ff4e
5
5
  SHA512:
6
- metadata.gz: 2adca44aac667b274f31b374f2914a9499f2c37294ef3d308ac45fd0fd0da26e0545093d62c508d42b5c78638e181e10b1c1f3b252396c0ca8a5a952a54dd509
7
- data.tar.gz: c1b6ab154c81408296714795d68521135da81bb0ca5226b9407c600f824cc566333f1f022cbd088d71629be94d83494ab2c94d41d71c178a2034e94b697288fd
6
+ metadata.gz: fa204f488a45f055b602e9baf8504cd64e8a91404a69800588065fcabbfa5a85ce2ae9220751fdf7633facdfe1627a98bae33354eabfaf6c64e9053f20f6472a
7
+ data.tar.gz: ba2fbe421642ed72bff9e023b541c4321c56baa653f54f1ac372d3e7d43233691a7316040340ff20c94e1d4fab6ceb5ce314fe0efeadfa65240e2dee2042593e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- trk_datatables (0.2.8)
4
+ trk_datatables (0.2.13)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -52,4 +52,4 @@ DEPENDENCIES
52
52
  trk_datatables!
53
53
 
54
54
  BUNDLED WITH
55
- 2.1.4
55
+ 2.2.15
data/README.md CHANGED
@@ -256,7 +256,7 @@ For specific columns you can use following keys
256
256
  * `order: false` disable ordering for this column
257
257
  * `select_options: Post.statuses` generate select box instead of text input
258
258
  * `predefined_ranges: {}` for datetime fiels add ranges to pick up from
259
- * `hide: true` hide column with display none
259
+ * `hide: true` hide column with display none, for example `{ hide: @view.params[:user_id].present? }`
260
260
  * `class_name: 'Admin::User'` use different class name than
261
261
  `table_name.classify` (in this case of `admin_users` will be `AdminUser`)
262
262
  * `column_type_in_db` one of the: `:string`, `:integer`, `:date`, `:datetime`,
@@ -332,7 +332,7 @@ def columns
332
332
  end
333
333
 
334
334
  # in view
335
- link_to 'Active', search_posts_path(PostsDatatable.param_set('posts.status':
335
+ link_to 'Active', search_posts_path(PostsDatatable.param_set('posts.status',
336
336
  Post.statues.values_at(:published, :promoted)))
337
337
  ```
338
338
 
@@ -531,6 +531,94 @@ class MostLikedPostsDatatable < TrkDatatables::ActiveRecord
531
531
  end
532
532
  ```
533
533
 
534
+ ### Table less models
535
+
536
+ You can use raw sql to fetch the data and use it as a model.
537
+ Here is an example when there is no relations to other models
538
+ ```
539
+ # app/models/table_less.rb
540
+ class TableLess < ApplicationRecord
541
+ self.abstract_class = true
542
+
543
+ def self.load_schema!
544
+ @columns_hash ||= {}
545
+
546
+ # From active_record/attributes.rb
547
+ attributes_to_define_after_schema_loads.each do |name, (type, options)|
548
+ type = ActiveRecord::Type.lookup(type, **options.except(:default)) if type.is_a?(Symbol)
549
+
550
+ define_attribute(name, type, **options.slice(:default))
551
+
552
+ # Improve Model#inspect output
553
+ @columns_hash[name.to_s] = ActiveRecord::ConnectionAdapters::Column.new(name.to_s, options[:default])
554
+ end
555
+ end
556
+ end
557
+ ```
558
+
559
+ ```
560
+ # app/models/translation.rb
561
+ class Translation < TableLess
562
+ self.table_name = :translations
563
+
564
+ attribute :translateable_type, :string, default: nil
565
+ attribute :translateable_id, :string, default: nil
566
+ attribute :column_name, :string, default: nil
567
+ attribute :column_value, :string, default: nil
568
+
569
+ belongs_to :translateable, polymorphic: true
570
+ end
571
+ ```
572
+
573
+ ```
574
+ # app/datatables/translations_datatable.rb
575
+ # rubocop:disable Layout/LineLength
576
+ class TranslationsDatatable < BaseDatatable
577
+ def columns
578
+ {
579
+ 'translations.translateable_id': {},
580
+ 'translations.translateable_type': {hide: true},
581
+ 'translations.column_name': {},
582
+ 'translations.column_value': {},
583
+ '': {},
584
+ }
585
+ end
586
+
587
+ def all_items
588
+ sql = <<~SQL.squish
589
+ (
590
+ (SELECT 'Activity' AS translateable_type, id AS translateable_id, 'name' AS column_name, name AS column_value FROM activities)
591
+ UNION
592
+ (SELECT 'Activity' AS translateable_type, id AS translateable_id, 'description' AS column_name, description AS column_value FROM activities)
593
+ ) as translations
594
+ SQL
595
+ Translation.from([Arel.sql(sql)])
596
+ end
597
+
598
+ def rows(filtered)
599
+ filtered.map do |translation|
600
+ edit_link = @view.button_tag_open_modal(
601
+ @view.edit_translation_path(translation.translateable_id, translateable_type: translation.translateable_type, column_name: translation.column_name), title: @view.t_crud('edit', Translation)
602
+ )
603
+ [
604
+ @view.link_to(translation.translateable, translation.translateable),
605
+ translation.translateable_type,
606
+ translation.column_name,
607
+ translation.column_value,
608
+ edit_link,
609
+ ]
610
+ end
611
+ end
612
+ end
613
+ # rubocop:enable Layout/LineLength
614
+ ```
615
+
616
+ For column title we use `table_class.human_attribute_name column_name`. When
617
+ calculated_ columns is used than it can not find translation so better is to:
618
+ ```
619
+ 'string_calculated_in_db.column_value_translated': {search: false, title: @view.t('activerecord.attributes.translation.column_value_translated')},
620
+ ```
621
+
534
622
  ### Default order and page length
535
623
 
536
624
  You can override default order (index and direction) and default page length so
@@ -552,12 +640,41 @@ class PostsDatatable
552
640
  end
553
641
  ```
554
642
 
643
+ ### Render html with additional css class and different DOM
644
+
645
+ To add additional styling to your datatable you can use `:class` option when you
646
+ are calling `@datatable.render_html url, options` for example
647
+
648
+ ```
649
+ <%= @datatable.render_html search_posts_path(format: :json), class: 'table-hover' %>
650
+ ```
651
+
652
+ Default [DOM](https://datatables.net/reference/option/dom) is
653
+ `<"trk-global-search-wrapper"f>rtp<"trk-move-up"il>` which includes global
654
+ **f**iltering, p**r**ocessing loader, **t**able search, **p**agination, table
655
+ **i**nformation and **l**ength changing control. To override you can use
656
+
657
+ ```
658
+ <%= @datatable.render_html search_posts_path(format: :json), 'data-datatable-dom': 'rt' %>
659
+ ```
660
+
555
661
  ### Params
556
662
 
557
663
  To set parameters that you can use for links to set column search value, use
558
664
  this `PostsDatatable.param_set 'users.email', 'my@email.com'`. For between
559
665
  search you can use range `Time.zone.today..(Time.zone.today + 1.year)` and for
560
- in multiple values use array `[Post.statuses[:draft]]`.
666
+ in multiple values use array `[Post.statuses[:draft]]`. Note that in Rails
667
+ `Time.zone.now.to_s` usually returns seconds ('23:59:59') but if you change
668
+ default format like in `config/initializers/time_formats.rb` with
669
+ `Time::DATE_FORMATS[:default] = '%d-%b-%Y %I:%M %p'` than range
670
+ `Time.zone.now.at_beginning_of_day..Time.zone.now.at_end_of_day` will not
671
+ include those at end of day since param will not include seconds ('23:59') so in
672
+ this case you can use range for strings
673
+ `Time.zone.now.at_beginning_of_day.to_s..Time.zone.now.at_end_of_day.to_s(:with_seconds)`
674
+ and config/initializers/time_formats.rb `Time::DATE_FORMATS[:with_seconds] = '%d-%b-%Y %I:%M:%S %p'`
675
+
676
+ (or use date `Time.zone.today..Time.zone.today` but that will not populate
677
+ datetime fields in dateRangePicker correctly)
561
678
 
562
679
  ```
563
680
  <%= link_to 'Active posts for my@email.com', \
@@ -573,6 +690,15 @@ in multiple values use array `[Post.statuses[:draft]]`.
573
690
  This will fill proper column search values so you do not need to do it manually
574
691
  (`post_path(:columns=>{"3"=>{:search=>{:value=>"my@email.com"}},
575
692
  "2"=>{:search=>{:value=>"1|2"}}}, :user_id=>1)`)
693
+ Please note that user_id is not inside datatable params so it will not be used
694
+ for next search params (all other search params are used with Datatables and
695
+ will remain on next search) so you need to manually add that param
696
+ ```
697
+ <%= @datatable.render_html search_posts_path(user_id: params[:user_id], format: :json) %>
698
+ ```
699
+
700
+ You can use generic name `params[:non_table_filter]` and split with colon
701
+ `user_id:123` but that is not needed.
576
702
 
577
703
  For form fields you can use similar helper that will return name which points to
578
704
  specific column, for example:
@@ -596,10 +722,39 @@ For global search you can use `[search][value]` for example
596
722
  <% end %>
597
723
  ```
598
724
 
599
- If you need, you can fetch params with this helper
725
+ If you need, you can fetch params with this helper and for example, show the
726
+ link for that record
600
727
 
601
728
  ```
602
- PostsDatatable.param_get('users.email', params)
729
+ if @datatable.param_get("locations.name").present? &&
730
+ (location = Location.find_by(name: @datatable.param_get("locations.name")))
731
+ page_description "For <a href='#{location_path(location)}'>#{location.name}</a>"
732
+ breadcrumb "Dashboard": dashboard_path, location.name => location_path(location), "Package Sales": nil
733
+ else
734
+ breadcrumb "Dashboard": dashboard_path, "Package Sales": nil
735
+ end
736
+ ```
737
+
738
+ For other filter params which are not in columns you can use non table params
739
+ ```
740
+ # on dashboard
741
+ <%= link_to 'Locations', isp_locations_path(non_table_filter: "reseller_operator_id:#{@reseller_operator.id}") %>
742
+
743
+ # on index
744
+ if params[:non_table_filter].present? &&
745
+ (reseller_operator = ResellerOperator.find(params[:non_table_filter].split(":").second))
746
+ page_description "For <a href='#{reseller_operator_path(reseller_operator)}'>#{reseller_operator.company_name}</a>"
747
+ breadcrumb 'Dashboard' => isp_dashboard_path, reseller_operator.company_name => reseller_operator_path(reseller_operator), 'Locations' => nil
748
+ else
749
+ breadcrumb 'Dashboard' => isp_dashboard_path, 'Locations' => nil
750
+ end
751
+
752
+ # in datatables
753
+ case @view.params[:non_table_filter].to_s.split(':').first
754
+ when 'reseller_operator_id'
755
+ reseller_operator = ResellerOperator.find @view.params[:non_table_filter].split(':').second
756
+ all_isp_locations = all_isp_locations.where(reseller_operator: reseller_operator)
757
+ end
603
758
  ```
604
759
 
605
760
  You can set filters on datatable even params are blank, for example
@@ -661,7 +816,9 @@ end
661
816
 
662
817
  You can use condition to provide different data, for example let's assume
663
818
  `@view.api_user?` returns true for json requests from mobile app. Here is
664
- example that provides different columns for normal and api_user:
819
+ example that provides different columns for normal and api_user.
820
+ Note that when you are using different columns for some reason in `@view` you
821
+ need to provide view in `param_set` so it can check the same conditionals.
665
822
 
666
823
  ```
667
824
  # app/datatables/posts_datatable.rb
@@ -671,8 +828,14 @@ class PostsDatatable < TrkDatatables::ActiveRecord
671
828
  end
672
829
 
673
830
  def columns_for_html
831
+ balance = @view.current_location
832
+ {}
833
+ else
834
+ { 'integer_calculated_in_db.balance_amount_in_cents': { search: false, title: 'Balance' } }
835
+ end
674
836
  {
675
837
  'subscribers.subscriberid': {},
838
+ **balance,
676
839
  'subscribers.name': {},
677
840
  }
678
841
  end
@@ -691,8 +854,14 @@ class PostsDatatable < TrkDatatables::ActiveRecord
691
854
 
692
855
  def rows_for_html(filtered)
693
856
  filtered.map do |subscriber|
857
+ balance = if Constant.STILL_WITH_OLD_CODE
858
+ []
859
+ else
860
+ [@view.humanized_money_with_symbol(Money.new(location.balance_amount_in_cents)) : 'NA']
861
+ end
694
862
  [
695
863
  @view.link_to(subscriber.subscriberid, subscriber),
864
+ *balance,
696
865
  subscriber.name,
697
866
  ]
698
867
  end
@@ -712,6 +881,10 @@ class PostsDatatable < TrkDatatables::ActiveRecord
712
881
  @view.api_user? ? columns_for_api : nil
713
882
  end
714
883
  end
884
+
885
+ # On some dashboard page provide @view using `self` to param_set
886
+ link_to 'Active', search_posts_path(PostsDatatable.param_set('posts.status',
887
+ :active, self))
715
888
  ```
716
889
 
717
890
  ## Test your datatables
@@ -87,12 +87,15 @@ module TrkDatatables
87
87
  # we do not need to cast from string since range will do automatically
88
88
  parsed_from = from
89
89
  parsed_to = to
90
- when :date, :datetime
90
+ when :date
91
+ parsed_from = _parse_in_zone(from).to_date
92
+ parsed_to = _parse_in_zone(to).to_date
93
+ when :datetime
91
94
  parsed_from = _parse_in_zone(from)
92
95
  parsed_to = _parse_in_zone(to)
93
- if parsed_to.present? && !to.match(/AM|PM/)
94
- # we need to add one day since it looks at begining of a day 2010-10-10 00:00:00
95
- parsed_to += 60 * 60 * 24 - 1
96
+ if parsed_to.present? && !to.match(/:/)
97
+ # Use end of a day if time is not defined, for example 2020-02-02
98
+ parsed_to = parsed_to.at_end_of_day
96
99
  end
97
100
  end
98
101
  [parsed_from, parsed_to]
@@ -241,10 +241,7 @@ module TrkDatatables
241
241
  'Last Month':
242
242
  Time.zone.today.prev_month.beginning_of_month.beginning_of_day...Time.zone.today.prev_month.end_of_month.end_of_day,
243
243
  'This Year': Time.zone.today.beginning_of_year.beginning_of_day...Time.zone.today.end_of_day,
244
- }.transform_values do |range|
245
- # datepicker expects format 2020-11-29 11:59:59
246
- range.first.strftime('%F %T')..range.last.strftime('%F %T')
247
- end
244
+ }
248
245
  end
249
246
  end
250
247
  end
@@ -13,8 +13,8 @@ module TrkDatatables
13
13
  # @example
14
14
  # link_to 'Published posts for user1',
15
15
  # posts_path(PostsDatatable.param_set('posts.status', :published).merge(user_id: user1.id))
16
- def param_set(column_key, value)
17
- datatable = new OpenStruct.new(params: {})
16
+ def param_set(column_key, value, view = nil)
17
+ datatable = new view || OpenStruct.new(params: {})
18
18
  value = value.join MULTIPLE_OPTION_SEPARATOR if value.is_a? Array
19
19
  value = [value.first, value.last].join BETWEEN_SEPARATOR if value.is_a? Range
20
20
  column_index = datatable.index_by_column_key column_key
@@ -172,7 +172,12 @@ module TrkDatatables
172
172
  # This is helper
173
173
  def _determine_string_type_cast # :nodoc:
174
174
  if defined?(::ActiveRecord::Base)
175
- DB_ADAPTER_STRING_TYPE_CAST[::ActiveRecord::Base.connection_config[:adapter].to_sym]
175
+ current_adapter = if ::ActiveRecord::Base.respond_to?(:connection_db_config)
176
+ ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter]
177
+ else
178
+ ::ActiveRecord::Base.connection_config[:adapter]
179
+ end
180
+ DB_ADAPTER_STRING_TYPE_CAST[current_adapter.to_sym]
176
181
  else
177
182
  'not_used'
178
183
  end
@@ -117,7 +117,7 @@ module TrkDatatables
117
117
  def param_get(column_index)
118
118
  @params.dig :columns, column_index.to_s, :search, :value
119
119
  rescue TypeError => e
120
- raise Error, e.message + '. Column search is in a format: { "columns": { "0": { "search": { "value": { "ABC" } } } } }'
120
+ raise Error, "#{e.message}. Column search is in a format: { \"columns\": { \"0\": { \"search\": { \"value\": { \"ABC\" } } } } }"
121
121
  end
122
122
 
123
123
  def self.sample_view_params(options = {})
@@ -4,7 +4,7 @@ module TrkDatatables
4
4
  def initialize(search_link, datatable, html_options = {})
5
5
  @search_link = search_link
6
6
  @datatable = datatable
7
- @html_options = html_options
7
+ @html_options = html_options.symbolize_keys
8
8
  self.class.indent = 0
9
9
  end
10
10
 
@@ -89,6 +89,7 @@ module TrkDatatables
89
89
  # for initial page load we do not have ability to show recordsTotal
90
90
  # https://github.com/trkin/trk_datatables_js/issues/1
91
91
  'data-datatable-total-length': @datatable.filtered_items_count,
92
+ 'data-datatable-dom': @html_options[:'data-datatable-dom'] || '<"trk-global-search-wrapper"f>rtp<"trk-move-up"il>',
92
93
  ) do
93
94
  thead << "\n".html_safe << tbody
94
95
  end +
@@ -1,3 +1,3 @@
1
1
  module TrkDatatables
2
- VERSION = '0.2.8'.freeze
2
+ VERSION = '0.2.13'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trk_datatables
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dusan Orlovic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-22 00:00:00.000000000 Z
11
+ date: 2021-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -220,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
222
  requirements: []
223
- rubygems_version: 3.0.8
223
+ rubygems_version: 3.2.15
224
224
  signing_key:
225
225
  specification_version: 4
226
226
  summary: Gem that simplify using datatables with Ruby on Rails and Sinatra.