infotable 0.1.0

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +1043 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/javascripts/infotable/controllers/drawer_controller.js +1412 -0
  6. data/app/assets/javascripts/infotable/controllers/table_controller.js +921 -0
  7. data/app/assets/javascripts/infotable/index.js +14 -0
  8. data/app/controllers/infotable/application_controller.rb +4 -0
  9. data/app/controllers/infotable/tables_controller.rb +299 -0
  10. data/app/helpers/infotable/application_helper.rb +5 -0
  11. data/app/helpers/infotable/tables_helper.rb +354 -0
  12. data/app/jobs/infotable/application_job.rb +4 -0
  13. data/app/mailers/infotable/application_mailer.rb +6 -0
  14. data/app/models/infotable/application_record.rb +5 -0
  15. data/app/views/infotable/tables/_column_visibility.html.erb +100 -0
  16. data/app/views/infotable/tables/_filter_drawer.html.erb +65 -0
  17. data/app/views/infotable/tables/_next_page_frame.html.erb +39 -0
  18. data/app/views/infotable/tables/_pagination.html.erb +101 -0
  19. data/app/views/infotable/tables/_side_panel.html.erb +63 -0
  20. data/app/views/infotable/tables/_table.html.erb +135 -0
  21. data/app/views/infotable/tables/_table_rows.html.erb +38 -0
  22. data/app/views/infotable/tables/filters/_boolean.html.erb +22 -0
  23. data/app/views/infotable/tables/filters/_date.html.erb +30 -0
  24. data/app/views/infotable/tables/filters/_number.html.erb +32 -0
  25. data/app/views/infotable/tables/filters/_select.html.erb +68 -0
  26. data/app/views/infotable/tables/filters/_text.html.erb +38 -0
  27. data/app/views/infotable/tables/show.html.erb +113 -0
  28. data/app/views/layouts/infotable/application.html.erb +15 -0
  29. data/config/importmap.rb +6 -0
  30. data/config/locales/en.yml +88 -0
  31. data/config/locales/pl.yml +88 -0
  32. data/config/routes.rb +6 -0
  33. data/lib/generators/infotable/install/install_generator.rb +565 -0
  34. data/lib/generators/infotable/install/templates/TAILWIND_CONFIG.md +131 -0
  35. data/lib/generators/infotable/install/templates/initializer.rb +26 -0
  36. data/lib/generators/infotable/install/templates/tailwind.config.js +284 -0
  37. data/lib/generators/infotable/table/table_generator.rb +95 -0
  38. data/lib/generators/infotable/table/templates/table.rb.tt +26 -0
  39. data/lib/infotable/base.rb +463 -0
  40. data/lib/infotable/batch_actions.rb +34 -0
  41. data/lib/infotable/configuration.rb +53 -0
  42. data/lib/infotable/engine.rb +51 -0
  43. data/lib/infotable/filter_processor.rb +326 -0
  44. data/lib/infotable/formatters/action_formatter.rb +141 -0
  45. data/lib/infotable/formatters/avatar_formatter.rb +49 -0
  46. data/lib/infotable/formatters/badge_formatter.rb +80 -0
  47. data/lib/infotable/formatters/base_formatter.rb +47 -0
  48. data/lib/infotable/formatters/boolean_formatter.rb +38 -0
  49. data/lib/infotable/formatters/currency_formatter.rb +22 -0
  50. data/lib/infotable/formatters/date_formatter.rb +58 -0
  51. data/lib/infotable/formatters/link_formatter.rb +48 -0
  52. data/lib/infotable/formatters/percent_formatter.rb +27 -0
  53. data/lib/infotable/search_processor.rb +42 -0
  54. data/lib/infotable/table_resolver.rb +45 -0
  55. data/lib/infotable/version.rb +3 -0
  56. data/lib/infotable.rb +54 -0
  57. data/lib/tasks/infotable.rake +55 -0
  58. metadata +216 -0
@@ -0,0 +1,22 @@
1
+ module Infotable
2
+ module Formatters
3
+ class CurrencyFormatter < BaseFormatter
4
+ def format(value, record, options = {})
5
+ return "" if value.blank?
6
+
7
+ unit = options[:unit] || "$"
8
+ precision = options[:precision] || 2
9
+ delimiter = options[:delimiter] || ","
10
+ separator = options[:separator] || "."
11
+
12
+ number_to_currency(
13
+ value,
14
+ unit: unit,
15
+ precision: precision,
16
+ delimiter: delimiter,
17
+ separator: separator
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,58 @@
1
+ module Infotable
2
+ module Formatters
3
+ class DateFormatter < BaseFormatter
4
+ def format(value, record, options = {})
5
+ return "" if value.blank?
6
+
7
+ value = parse_value(value)
8
+ return value.to_s if value.is_a?(String)
9
+
10
+ format = options[:format] || :default
11
+
12
+ case format
13
+ when :short
14
+ value.strftime("%b %d, %Y")
15
+ when :long
16
+ value.strftime("%B %d, %Y")
17
+ when :time
18
+ value.strftime("%I:%M %p")
19
+ when :datetime
20
+ value.strftime("%b %d, %Y %I:%M %p")
21
+ when :relative
22
+ time_ago_in_words(value)
23
+ when :dot_date
24
+ value.strftime("%d.%m.%Y")
25
+ when :default
26
+ # Use Rails default
27
+ value.strftime("%Y-%m-%d %H:%M")
28
+ else
29
+ # Custom format string
30
+ if format.is_a?(String)
31
+ value.strftime(format)
32
+ else
33
+ # Try to use I18n localization
34
+ begin
35
+ view_context.l(value, format: format)
36
+ rescue
37
+ value.strftime("%Y-%m-%d %H:%M")
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def parse_value(value)
46
+ return value unless value.is_a?(String)
47
+
48
+ Time.zone.parse(value) || value
49
+ rescue ArgumentError
50
+ value
51
+ end
52
+
53
+ def time_ago_in_words(value)
54
+ view_context.t("infotable.formatters.ago", time: view_context.time_ago_in_words(value))
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,48 @@
1
+ module Infotable
2
+ module Formatters
3
+ # formatter: :link
4
+ # formatter_options: {
5
+ # url: ->(record) { user_path(record) }, # Proc (run in the view), Symbol (helper method) or String
6
+ # label: ->(record) { record.email }, # optional, defaults to the cell value
7
+ # external: true, # target=_blank rel="noopener noreferrer"
8
+ # class: "..." # replaces the default classes
9
+ # }
10
+ # Without url: the value itself is the URL (handy for website columns); mailto:/tel: work too.
11
+ class LinkFormatter < BaseFormatter
12
+ ALLOWED_SCHEMES = %w[http https mailto tel].freeze
13
+ DEFAULT_CLASSES = "text-indigo-600 hover:text-indigo-800 hover:underline".freeze
14
+
15
+ def format(value, record, options = {})
16
+ label = resolve(options[:label], record) || value
17
+ return "" if label.blank? && value.blank?
18
+
19
+ url = options.key?(:url) ? resolve(options[:url], record) : value
20
+ return label.to_s unless self.class.safe_url?(url)
21
+
22
+ attributes = { href: url.to_s, class: options[:class] || DEFAULT_CLASSES }
23
+ attributes.merge!(target: "_blank", rel: "noopener noreferrer") if options[:external]
24
+
25
+ link_to(label.to_s, url.to_s, attributes)
26
+ end
27
+
28
+ # Relative URLs, http(s), mailto and tel. Everything else (javascript:, data:, ...) is rendered as text.
29
+ def self.safe_url?(url)
30
+ return false if url.blank?
31
+
32
+ cleaned = url.to_s.gsub(/[[:cntrl:][:space:]]/, "")
33
+ scheme = cleaned[/\A([a-z][a-z0-9+.\-]*):/i, 1]
34
+ scheme.nil? || ALLOWED_SCHEMES.include?(scheme.downcase)
35
+ end
36
+
37
+ private
38
+
39
+ def resolve(option, record)
40
+ case option
41
+ when Proc then view_context.instance_exec(record, &option)
42
+ when Symbol then view_context.send(option, record)
43
+ else option
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ module Infotable
2
+ module Formatters
3
+ # formatter: :percent
4
+ # formatter_options: {
5
+ # precision: 1, # decimals, default 0
6
+ # scale: :percent, # :percent (value is 0-100, default) or :ratio (value is 0-1)
7
+ # bar: true # small progress bar next to the number
8
+ # }
9
+ class PercentFormatter < BaseFormatter
10
+ def format(value, record, options = {})
11
+ return "" if value.nil? || value == ""
12
+
13
+ number = Float(value.to_s, exception: false)
14
+ return value.to_s if number.nil?
15
+
16
+ number *= 100 if options[:scale].to_s == "ratio"
17
+ text = view_context.number_to_percentage(number, precision: options.fetch(:precision, 0), strip_insignificant_zeros: false)
18
+ return text unless options[:bar]
19
+
20
+ width = number.clamp(0, 100).round
21
+ bar = content_tag(:div, content_tag(:div, "", class: "h-full rounded-full bg-indigo-500", style: "width: #{width}%"),
22
+ class: "h-1.5 w-16 rounded-full bg-gray-200 flex-none", role: "presentation")
23
+ content_tag(:div, safe_join([ content_tag(:span, text, class: "tabular-nums"), bar ]), class: "flex items-center gap-2")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ module Infotable
2
+ # Global search: every whitespace-separated term must match (ILIKE) at least one
3
+ # searchable column. Non-text columns are matched on their text representation.
4
+ class SearchProcessor
5
+ MAX_TERMS = 5
6
+ MAX_TERM_LENGTH = 100
7
+
8
+ attr_reader :query, :table_class, :term
9
+
10
+ def initialize(query, table_class, term)
11
+ @query = query
12
+ @table_class = table_class
13
+ @term = term.to_s.delete("\u0000") # PostgreSQL rejects NUL bytes
14
+ end
15
+
16
+ def apply
17
+ columns = searchable_columns
18
+ return query if columns.empty?
19
+
20
+ terms.reduce(query) do |relation, word|
21
+ pattern = "%#{ActiveRecord::Base.sanitize_sql_like(word)}%"
22
+ conditions = columns.map { "CAST(#{column_ref(_1)} AS text) ILIKE :pattern" }
23
+ relation.where(conditions.join(" OR "), pattern: pattern)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def terms
30
+ term.split.first(MAX_TERMS).map { _1.first(MAX_TERM_LENGTH) }
31
+ end
32
+
33
+ # Aggregate (HAVING) columns can't be searched with WHERE
34
+ def searchable_columns
35
+ table_class.searchable_columns.reject { |col| col[:virtual] && col[:sql].blank? }
36
+ end
37
+
38
+ def column_ref(column)
39
+ column[:sql].presence || "#{query.model.table_name}.#{column[:name]}"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,45 @@
1
+ module Infotable
2
+ # Resolves a table name (:users_table, "cms_admins_users_table", "order_items_table")
3
+ # to its Infotable::Base subclass.
4
+ #
5
+ # Underscores are ambiguous (namespace separator or word separator), so every way of
6
+ # grouping the parts into namespaces is tried, flattest first:
7
+ # order_items -> OrderItemsTable, Order::ItemsTable, OrderItems::Table ...
8
+ # Only classes inheriting from Infotable::Base are accepted.
9
+ module TableResolver
10
+ MAX_PARTS = 8
11
+
12
+ class NotFound < Infotable::Error; end
13
+
14
+ module_function
15
+
16
+ def resolve(table_name)
17
+ candidates(table_name).each do |class_name|
18
+ klass = class_name.safe_constantize
19
+ return klass if klass.is_a?(Class) && klass < Infotable::Base
20
+ end
21
+
22
+ raise NotFound, "Table '#{table_name}' not found. Make sure it's defined in app/infotable/"
23
+ end
24
+
25
+ def candidates(table_name)
26
+ return [] unless table_name.to_s.match?(/\A[a-z0-9]+(_[a-z0-9]+)*\z/i)
27
+
28
+ parts = table_name.to_s.sub(/_table\z/, "").split("_")
29
+ return [] if parts.empty? || parts.size > MAX_PARTS
30
+
31
+ (0...(2**(parts.size - 1))).map { |mask| segments(parts, mask) }
32
+ .sort_by(&:size)
33
+ .map { |segs| segs.map(&:camelize).join("::").sub(/([^:]+)\z/, '\1Table') }
34
+ .uniq
35
+ end
36
+
37
+ # Bit i of mask set => split between part i and i+1
38
+ def segments(parts, mask)
39
+ parts.each_with_index.each_with_object([ [] ]) do |(part, i), acc|
40
+ acc.last << part
41
+ acc << [] if i < parts.size - 1 && mask[i] == 1
42
+ end.map { |seg| seg.join("_") }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module Infotable
2
+ VERSION = "0.1.0"
3
+ end
data/lib/infotable.rb ADDED
@@ -0,0 +1,54 @@
1
+ require "infotable/version"
2
+ require "infotable/configuration"
3
+ require "infotable/engine"
4
+
5
+ module Infotable
6
+ class Error < StandardError; end
7
+
8
+ # Autoload core components
9
+ autoload :Base, "infotable/base"
10
+ autoload :FilterProcessor, "infotable/filter_processor"
11
+ autoload :BatchActions, "infotable/batch_actions"
12
+ autoload :SearchProcessor, "infotable/search_processor"
13
+ autoload :TableResolver, "infotable/table_resolver"
14
+
15
+ # Formatters
16
+ module Formatters
17
+ autoload :BaseFormatter, "infotable/formatters/base_formatter"
18
+ autoload :DateFormatter, "infotable/formatters/date_formatter"
19
+ autoload :CurrencyFormatter, "infotable/formatters/currency_formatter"
20
+ autoload :BooleanFormatter, "infotable/formatters/boolean_formatter"
21
+ autoload :BadgeFormatter, "infotable/formatters/badge_formatter"
22
+ autoload :ActionFormatter, "infotable/formatters/action_formatter"
23
+ autoload :LinkFormatter, "infotable/formatters/link_formatter"
24
+ autoload :AvatarFormatter, "infotable/formatters/avatar_formatter"
25
+ autoload :PercentFormatter, "infotable/formatters/percent_formatter"
26
+ end
27
+
28
+ # Returns the root path of the InfoTable gem
29
+ def self.root
30
+ Engine.root
31
+ end
32
+
33
+ # Returns the path to InfoTable views directory
34
+ # For use in Tailwind CSS @source directives via ERB
35
+ def self.views_path
36
+ root.join("app/views/infotable").to_s
37
+ end
38
+
39
+ # Returns the path to InfoTable formatters directory
40
+ # For use in Tailwind CSS @source directives via ERB
41
+ def self.formatters_path
42
+ root.join("lib/infotable/formatters").to_s
43
+ end
44
+
45
+ # Returns paths that should be scanned by Tailwind CSS
46
+ # For use with Node-based Tailwind (tailwind.config.js)
47
+ def self.tailwind_content_paths
48
+ [
49
+ root.join("app/views/infotable/**/*.{erb,html,rb}").to_s,
50
+ root.join("lib/infotable/formatters/**/*.rb").to_s,
51
+ root.join("app/assets/javascripts/infotable/**/*.js").to_s
52
+ ]
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ namespace :infotable do
2
+ desc "Generate infotable.css from ERB template with resolved gem paths"
3
+ task generate_tailwind_sources: :environment do
4
+ # Find the ERB template
5
+ erb_path = if File.exist?("app/assets/stylesheets/infotable.css.erb")
6
+ "app/assets/stylesheets/infotable.css.erb"
7
+ elsif File.exist?("app/assets/tailwind/infotable.css.erb")
8
+ "app/assets/tailwind/infotable.css.erb"
9
+ else
10
+ puts "⚠️ infotable.css.erb not found. Run 'rails generate infotable:install' first."
11
+ next
12
+ end
13
+
14
+ output_path = erb_path.sub(".erb", "")
15
+
16
+ # Read and process the ERB template
17
+ require "erb"
18
+ template = File.read(erb_path)
19
+ result = ERB.new(template).result(binding)
20
+
21
+ # Write the generated CSS
22
+ File.write(output_path, result)
23
+
24
+ puts "✅ Generated #{output_path} from ERB template"
25
+ puts " Views: #{Infotable.views_path}"
26
+ puts " Formatters: #{Infotable.formatters_path}"
27
+ end
28
+
29
+ # Alias for backwards compatibility
30
+ task update_tailwind_paths: :generate_tailwind_sources
31
+
32
+ desc "Display InfoTable gem paths for Tailwind CSS (for debugging)"
33
+ task show_tailwind_paths: :environment do
34
+ puts "\n" + "=" * 60
35
+ puts "InfoTable Gem Paths"
36
+ puts "=" * 60
37
+ puts "Gem root: #{Infotable.root}"
38
+ puts "Views path: #{Infotable.views_path}"
39
+ puts "Formatters path: #{Infotable.formatters_path}"
40
+ puts "=" * 60 + "\n"
41
+ end
42
+ end
43
+
44
+ # Hook into Tailwind CSS build tasks
45
+ if Rake::Task.task_defined?("tailwindcss:build")
46
+ Rake::Task["tailwindcss:build"].enhance([ "infotable:generate_tailwind_sources" ])
47
+ end
48
+
49
+ if Rake::Task.task_defined?("tailwindcss:watch")
50
+ Rake::Task["tailwindcss:watch"].enhance([ "infotable:generate_tailwind_sources" ])
51
+ end
52
+
53
+ if Rake::Task.task_defined?("assets:precompile")
54
+ Rake::Task["assets:precompile"].enhance([ "infotable:generate_tailwind_sources" ])
55
+ end
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: infotable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jakub Cieślar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-10-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '8.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '8.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: csv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: turbo-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: stimulus-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pagy
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '43.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '43.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pg
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: puma
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: propshaft
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: InfoTable provides server-side datatable functionality with filtering,
126
+ sorting, searching, and pagination. Built with Hotwire, Stimulus, and Tailwind CSS
127
+ for a modern, no-reload user experience.
128
+ email:
129
+ - jakub@infovation.pl
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - MIT-LICENSE
135
+ - README.md
136
+ - Rakefile
137
+ - app/assets/javascripts/infotable/controllers/drawer_controller.js
138
+ - app/assets/javascripts/infotable/controllers/table_controller.js
139
+ - app/assets/javascripts/infotable/index.js
140
+ - app/controllers/infotable/application_controller.rb
141
+ - app/controllers/infotable/tables_controller.rb
142
+ - app/helpers/infotable/application_helper.rb
143
+ - app/helpers/infotable/tables_helper.rb
144
+ - app/jobs/infotable/application_job.rb
145
+ - app/mailers/infotable/application_mailer.rb
146
+ - app/models/infotable/application_record.rb
147
+ - app/views/infotable/tables/_column_visibility.html.erb
148
+ - app/views/infotable/tables/_filter_drawer.html.erb
149
+ - app/views/infotable/tables/_next_page_frame.html.erb
150
+ - app/views/infotable/tables/_pagination.html.erb
151
+ - app/views/infotable/tables/_side_panel.html.erb
152
+ - app/views/infotable/tables/_table.html.erb
153
+ - app/views/infotable/tables/_table_rows.html.erb
154
+ - app/views/infotable/tables/filters/_boolean.html.erb
155
+ - app/views/infotable/tables/filters/_date.html.erb
156
+ - app/views/infotable/tables/filters/_number.html.erb
157
+ - app/views/infotable/tables/filters/_select.html.erb
158
+ - app/views/infotable/tables/filters/_text.html.erb
159
+ - app/views/infotable/tables/show.html.erb
160
+ - app/views/layouts/infotable/application.html.erb
161
+ - config/importmap.rb
162
+ - config/locales/en.yml
163
+ - config/locales/pl.yml
164
+ - config/routes.rb
165
+ - lib/generators/infotable/install/install_generator.rb
166
+ - lib/generators/infotable/install/templates/TAILWIND_CONFIG.md
167
+ - lib/generators/infotable/install/templates/initializer.rb
168
+ - lib/generators/infotable/install/templates/tailwind.config.js
169
+ - lib/generators/infotable/table/table_generator.rb
170
+ - lib/generators/infotable/table/templates/table.rb.tt
171
+ - lib/infotable.rb
172
+ - lib/infotable/base.rb
173
+ - lib/infotable/batch_actions.rb
174
+ - lib/infotable/configuration.rb
175
+ - lib/infotable/engine.rb
176
+ - lib/infotable/filter_processor.rb
177
+ - lib/infotable/formatters/action_formatter.rb
178
+ - lib/infotable/formatters/avatar_formatter.rb
179
+ - lib/infotable/formatters/badge_formatter.rb
180
+ - lib/infotable/formatters/base_formatter.rb
181
+ - lib/infotable/formatters/boolean_formatter.rb
182
+ - lib/infotable/formatters/currency_formatter.rb
183
+ - lib/infotable/formatters/date_formatter.rb
184
+ - lib/infotable/formatters/link_formatter.rb
185
+ - lib/infotable/formatters/percent_formatter.rb
186
+ - lib/infotable/search_processor.rb
187
+ - lib/infotable/table_resolver.rb
188
+ - lib/infotable/version.rb
189
+ - lib/tasks/infotable.rake
190
+ homepage: https://infotable.infovation.eu/
191
+ licenses:
192
+ - MIT
193
+ metadata:
194
+ homepage_uri: https://infotable.infovation.eu/
195
+ source_code_uri: https://github.com/jcieslar/infotable
196
+ changelog_uri: https://github.com/jcieslar/infotable/blob/main/CHANGELOG.md
197
+ post_install_message:
198
+ rdoc_options: []
199
+ require_paths:
200
+ - lib
201
+ required_ruby_version: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ version: '3.3'
206
+ required_rubygems_version: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
211
+ requirements: []
212
+ rubygems_version: 3.5.16
213
+ signing_key:
214
+ specification_version: 4
215
+ summary: Modern, flexible datatable engine for Rails 8+ with Hotwire
216
+ test_files: []