admin_suite 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +134 -7
- data/app/assets/vendor/chart.umd.min.js +14 -0
- data/app/controllers/admin_suite/resources_controller.rb +130 -5
- data/app/helpers/admin_suite/base_helper.rb +187 -10
- data/app/javascript/admin_suite_application.js +3 -0
- data/app/javascript/controllers/admin_suite/chart_controller.js +173 -0
- data/app/views/admin_suite/panels/_chart.html.erb +158 -18
- data/app/views/admin_suite/resources/index.html.erb +24 -5
- data/app/views/admin_suite/shared/_sidebar.html.erb +14 -8
- data/app/views/layouts/admin_suite/application.html.erb +6 -0
- data/config/routes.rb +3 -0
- data/lib/admin/base/filter_builder.rb +48 -5
- data/lib/admin/base/resource.rb +43 -7
- data/lib/admin_suite/configuration.rb +10 -6
- data/lib/admin_suite/engine.rb +1 -1
- data/lib/admin_suite/legacy_custom_renderer_procs.rb +1 -1
- data/lib/admin_suite/renderer_registry.rb +11 -0
- data/lib/admin_suite/renderers/legacy_gleania.rb +7 -5
- data/lib/admin_suite/ui/dashboard_definition.rb +6 -0
- data/lib/admin_suite/version.rb +1 -1
- data/lib/admin_suite.rb +13 -2
- data/test/integration/association_linking_test.rb +292 -0
- data/test/integration/chart_panel_test.rb +491 -0
- data/test/integration/dashboard_test.rb +9 -2
- data/test/integration/index_table_test.rb +289 -0
- data/test/integration/navigation_sections_test.rb +21 -0
- data/test/integration/searchable_select_search_test.rb +368 -0
- data/test/integration/show_hide_blank_test.rb +195 -0
- data/test/integration/toggle_test.rb +106 -0
- data/test/lib/definition_loader_test.rb +12 -0
- data/test/lib/form_field_renderer_test.rb +83 -11
- data/test/lib/format_table_cell_test.rb +49 -0
- data/test/lib/index_includes_test.rb +223 -0
- data/test/lib/legacy_renderer_deprecation_test.rb +8 -1
- data/test/lib/renderer_test.rb +23 -7
- data/test/lib/resource_exportable_deprecation_test.rb +10 -2
- data/test/test_helper.rb +47 -8
- metadata +35 -5
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
# Fixtures for the `includes:` DSL option (Task 4, phase 2b). A scope that
|
|
6
|
+
# genuinely supports `#includes` and records/validates the call, so the
|
|
7
|
+
# controller's "apply when the scope responds" and "degrade when
|
|
8
|
+
# `.includes` itself raises" paths are both exercisable end-to-end. The
|
|
9
|
+
# `LinkingFixtures::Deal`/`ReadOnlyResourceFixtures::Relation` pair (no
|
|
10
|
+
# `#includes` at all) already covers the "skip silently" path -- reused
|
|
11
|
+
# below rather than duplicated.
|
|
12
|
+
module IndexIncludesFixtures
|
|
13
|
+
class IncludesCapableRelation
|
|
14
|
+
include Enumerable
|
|
15
|
+
|
|
16
|
+
KNOWN_ASSOCIATIONS = %i[company owner].freeze
|
|
17
|
+
|
|
18
|
+
attr_reader :includes_calls
|
|
19
|
+
|
|
20
|
+
def initialize(records)
|
|
21
|
+
@records = records
|
|
22
|
+
@includes_calls = []
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def each(&block) = @records.each(&block)
|
|
26
|
+
def count(*) = @records.count
|
|
27
|
+
def offset(*) = self
|
|
28
|
+
def limit(*) = self
|
|
29
|
+
|
|
30
|
+
# Mirrors real ActiveRecord's eventual `ActiveRecord::AssociationNotFoundError`
|
|
31
|
+
# for an unknown association name -- raised here at call time (rather
|
|
32
|
+
# than lazily, as real AR does) so the controller's rescue path around
|
|
33
|
+
# the `.includes` call site is directly exercisable.
|
|
34
|
+
def includes(*associations)
|
|
35
|
+
flat = associations.flatten
|
|
36
|
+
invalid = flat.reject { |a| KNOWN_ASSOCIATIONS.include?(a.respond_to?(:to_sym) ? a.to_sym : a) }
|
|
37
|
+
raise ArgumentError, "Association named #{invalid.first.inspect} was not found" if invalid.any?
|
|
38
|
+
|
|
39
|
+
@includes_calls << flat
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Widget
|
|
45
|
+
extend ActiveModel::Naming
|
|
46
|
+
|
|
47
|
+
attr_reader :id, :name
|
|
48
|
+
|
|
49
|
+
def initialize(id:, name:)
|
|
50
|
+
@id = id
|
|
51
|
+
@name = name
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
RELATION = IncludesCapableRelation.new([ new(id: 1, name: "Widget One") ])
|
|
55
|
+
|
|
56
|
+
def self.all = RELATION
|
|
57
|
+
def self.column_names = %w[id name]
|
|
58
|
+
def self.primary_key = "id"
|
|
59
|
+
def self.columns_hash = { "id" => Struct.new(:type).new(:integer) }
|
|
60
|
+
def self.find(id) = all.find { |w| w.to_param == id.to_s }
|
|
61
|
+
def to_param = id.to_s
|
|
62
|
+
def attributes = { "id" => id, "name" => name }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class BadWidget
|
|
66
|
+
extend ActiveModel::Naming
|
|
67
|
+
|
|
68
|
+
attr_reader :id, :name
|
|
69
|
+
|
|
70
|
+
def initialize(id:, name:)
|
|
71
|
+
@id = id
|
|
72
|
+
@name = name
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
RELATION = IncludesCapableRelation.new([ new(id: 1, name: "Bad Widget") ])
|
|
76
|
+
|
|
77
|
+
def self.all = RELATION
|
|
78
|
+
def self.column_names = %w[id name]
|
|
79
|
+
def self.primary_key = "id"
|
|
80
|
+
def self.columns_hash = { "id" => Struct.new(:type).new(:integer) }
|
|
81
|
+
def self.find(id) = all.find { |w| w.to_param == id.to_s }
|
|
82
|
+
def to_param = id.to_s
|
|
83
|
+
def attributes = { "id" => id, "name" => name }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Self-contained (this file is runnable standalone via
|
|
87
|
+
# `rake test TEST=test/lib/index_includes_test.rb`, so it can't reach
|
|
88
|
+
# into fixtures defined only in association_linking_test.rb): a scope
|
|
89
|
+
# with no `#includes` method at all, mirroring
|
|
90
|
+
# `ReadOnlyResourceFixtures::Relation`, backing a resource that
|
|
91
|
+
# nonetheless declares `includes :company`. Exercises the "skip
|
|
92
|
+
# silently, don't raise" path.
|
|
93
|
+
class NoIncludesWidget
|
|
94
|
+
extend ActiveModel::Naming
|
|
95
|
+
|
|
96
|
+
attr_reader :id, :name
|
|
97
|
+
|
|
98
|
+
def initialize(id:, name:)
|
|
99
|
+
@id = id
|
|
100
|
+
@name = name
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.all = ReadOnlyResourceFixtures::Relation.new([ new(id: 1, name: "Plain Widget") ])
|
|
104
|
+
def self.column_names = %w[id name]
|
|
105
|
+
def self.primary_key = "id"
|
|
106
|
+
def self.columns_hash = { "id" => Struct.new(:type).new(:integer) }
|
|
107
|
+
def self.find(id) = all.find { |w| w.to_param == id.to_s }
|
|
108
|
+
def to_param = id.to_s
|
|
109
|
+
def attributes = { "id" => id, "name" => name }
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
module Admin
|
|
114
|
+
module Resources
|
|
115
|
+
class IndexIncludesWidgetResource < Admin::Base::Resource
|
|
116
|
+
model IndexIncludesFixtures::Widget
|
|
117
|
+
portal :ops
|
|
118
|
+
section :observability
|
|
119
|
+
|
|
120
|
+
index do
|
|
121
|
+
columns { column :name }
|
|
122
|
+
includes :company, :owner
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class IndexIncludesBadWidgetResource < Admin::Base::Resource
|
|
127
|
+
model IndexIncludesFixtures::BadWidget
|
|
128
|
+
portal :ops
|
|
129
|
+
section :observability
|
|
130
|
+
|
|
131
|
+
index do
|
|
132
|
+
columns { column :name }
|
|
133
|
+
includes :nonexistent_association
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
class IndexIncludesNoIncludesWidgetResource < Admin::Base::Resource
|
|
138
|
+
model IndexIncludesFixtures::NoIncludesWidget
|
|
139
|
+
portal :ops
|
|
140
|
+
section :observability
|
|
141
|
+
|
|
142
|
+
index do
|
|
143
|
+
columns { column :name }
|
|
144
|
+
includes :company
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
module AdminSuite
|
|
151
|
+
class IndexIncludesTest < ActionDispatch::IntegrationTest
|
|
152
|
+
test "IndexConfig#includes stores the list of associations" do
|
|
153
|
+
config = Admin::Base::Resource::IndexConfig.new
|
|
154
|
+
config.includes(:company, :owner)
|
|
155
|
+
assert_equal [ :company, :owner ], config.includes_list
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
test "IndexConfig#includes defaults to an empty list" do
|
|
159
|
+
assert_equal [], Admin::Base::Resource::IndexConfig.new.includes_list
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
test "IndexConfig#includes drops a nil association instead of storing garbage" do
|
|
163
|
+
config = Admin::Base::Resource::IndexConfig.new
|
|
164
|
+
config.includes(nil)
|
|
165
|
+
assert_equal [], config.includes_list
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
test "IndexConfig#includes tolerates a String association name" do
|
|
169
|
+
config = Admin::Base::Resource::IndexConfig.new
|
|
170
|
+
config.includes("company")
|
|
171
|
+
assert_equal [ "company" ], config.includes_list
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
test "the DSL exposes includes: on a resource's index_config" do
|
|
175
|
+
assert_equal [ :company, :owner ], Admin::Resources::IndexIncludesWidgetResource.index_config.includes_list
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
test "the controller applies includes: to a scope that responds to includes" do
|
|
179
|
+
IndexIncludesFixtures::Widget::RELATION.includes_calls.clear
|
|
180
|
+
|
|
181
|
+
get "/internal/admin_suite/ops/index_includes_widgets"
|
|
182
|
+
assert_response :success
|
|
183
|
+
|
|
184
|
+
assert_equal [ [ :company, :owner ] ], IndexIncludesFixtures::Widget::RELATION.includes_calls
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
test "a scope whose includes raises for a bad association degrades instead of 500ing" do
|
|
188
|
+
logged = []
|
|
189
|
+
Rails.logger.stub(:warn, ->(msg) { logged << msg }) do
|
|
190
|
+
get "/internal/admin_suite/ops/index_includes_bad_widgets"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
assert_response :success
|
|
194
|
+
assert_includes response.body, "Bad Widget"
|
|
195
|
+
# The rescue in `apply_index_includes` logs the failure -- pinning
|
|
196
|
+
# that here so the "skipped silently" test below (which asserts NO
|
|
197
|
+
# warn fires) is actually distinguishing two different code paths,
|
|
198
|
+
# not just two tests that both happen to pass.
|
|
199
|
+
assert_equal 1, logged.size
|
|
200
|
+
assert_includes logged.first, "nonexistent_association"
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
test "a scope that does not respond to includes is skipped silently, not raised" do
|
|
204
|
+
refute IndexIncludesFixtures::NoIncludesWidget.all.respond_to?(:includes)
|
|
205
|
+
|
|
206
|
+
logged = []
|
|
207
|
+
Rails.logger.stub(:warn, ->(msg) { logged << msg }) do
|
|
208
|
+
get "/internal/admin_suite/ops/index_includes_no_includes_widgets"
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
assert_response :success
|
|
212
|
+
assert_includes response.body, "Plain Widget"
|
|
213
|
+
# `apply_index_includes`'s `respond_to?(:includes)` guard exists so a
|
|
214
|
+
# scope that can never support includes doesn't spam a warning on
|
|
215
|
+
# every request. Deleting that guard would still return a 200 here
|
|
216
|
+
# (the catch-all rescue produces an identical response), so the
|
|
217
|
+
# response alone doesn't prove the guard does anything -- this
|
|
218
|
+
# asserts its actual purpose: no warn fires on this path. Contrast
|
|
219
|
+
# with the bad-association test above, where one does.
|
|
220
|
+
assert_empty logged
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
@@ -24,7 +24,14 @@ module AdminSuite
|
|
|
24
24
|
end
|
|
25
25
|
assert_equal 1, logged.size
|
|
26
26
|
assert_includes logged.first, "deprecated"
|
|
27
|
-
|
|
27
|
+
# Deliberately a hardcoded literal, not read off
|
|
28
|
+
# DEPRECATION_MESSAGE_FORMAT: reading the version out of the constant
|
|
29
|
+
# under test and asserting the message contains it is true by
|
|
30
|
+
# construction (format() only substitutes %<key>s, never the version
|
|
31
|
+
# digits), so it can never fail on a wrong retarget -- exactly the
|
|
32
|
+
# property this test exists to catch. If the removal target changes
|
|
33
|
+
# again, this literal must be updated by hand; that's the point.
|
|
34
|
+
assert_includes logged.first, "0.6.0"
|
|
28
35
|
end
|
|
29
36
|
|
|
30
37
|
test "the gem no longer includes the host CustomRenderersHelper constant" do
|
data/test/lib/renderer_test.rb
CHANGED
|
@@ -116,7 +116,14 @@ module AdminSuite
|
|
|
116
116
|
assert_equal 1, logged.size
|
|
117
117
|
assert_includes logged.first, key.to_s
|
|
118
118
|
assert_includes logged.first, "deprecated"
|
|
119
|
-
|
|
119
|
+
# Deliberately a hardcoded literal, not read off
|
|
120
|
+
# DEPRECATION_MESSAGE_FORMAT: reading the version out of the constant
|
|
121
|
+
# under test and asserting the message contains it is true by
|
|
122
|
+
# construction (format() only substitutes %<key>s, never the version
|
|
123
|
+
# digits), so it can never fail on a wrong retarget -- exactly the
|
|
124
|
+
# property this test exists to catch. If the removal target changes
|
|
125
|
+
# again, this literal must be updated by hand; that's the point.
|
|
126
|
+
assert_includes logged.first, "0.6.0"
|
|
120
127
|
ensure
|
|
121
128
|
AdminSuite.config.custom_renderers.delete(key)
|
|
122
129
|
end
|
|
@@ -144,6 +151,12 @@ module AdminSuite
|
|
|
144
151
|
assert_includes html, "host-class-7"
|
|
145
152
|
refute_includes html, "Hello 7"
|
|
146
153
|
ensure
|
|
154
|
+
# `register_default` seeds AdminSuite's *permanent* default store (the
|
|
155
|
+
# same one the built-ins live in), so this probe key must be removed
|
|
156
|
+
# via `unregister_default` -- unlike `unregister`, which only ever
|
|
157
|
+
# touches the explicit store and would silently leave this key behind
|
|
158
|
+
# for every test that runs afterward.
|
|
159
|
+
AdminSuite::RendererRegistry.unregister_default(key)
|
|
147
160
|
if Admin::Renderers.const_defined?(:HostBeatsDefaultProbeRenderer, false)
|
|
148
161
|
Admin::Renderers.send(:remove_const, :HostBeatsDefaultProbeRenderer)
|
|
149
162
|
end
|
|
@@ -172,12 +185,15 @@ module AdminSuite
|
|
|
172
185
|
test "a registered renderer class wins over the built-in case branches" do
|
|
173
186
|
# :json_preview has a legacy case branch; a registered class must take it over.
|
|
174
187
|
#
|
|
175
|
-
# Task 4 registers :json_preview as a permanent alias to JsonRenderer
|
|
176
|
-
#
|
|
177
|
-
#
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
#
|
|
188
|
+
# Task 4 registers :json_preview as a permanent alias to JsonRenderer,
|
|
189
|
+
# but via `register_default` (the gem-defaults store), not `register`
|
|
190
|
+
# (the explicit store). `lookup` below only ever reads the explicit
|
|
191
|
+
# store, so `previous` is nil here -- there is no explicit registration
|
|
192
|
+
# to save or restore, and the `ensure` branch's plain `unregister` is
|
|
193
|
+
# a safe no-op that cannot touch the permanent default alias (which
|
|
194
|
+
# only `unregister_default` could remove). This test still needs the
|
|
195
|
+
# save/restore shape below in case some future test registers
|
|
196
|
+
# :json_preview explicitly and forgets to clean up after itself.
|
|
181
197
|
previous = AdminSuite::RendererRegistry.lookup(:json_preview)
|
|
182
198
|
AdminSuite::RendererRegistry.register(:json_preview, GreetingRenderer)
|
|
183
199
|
assert_includes render_custom_section(Record.new(6), :json_preview), "Hello 6"
|
|
@@ -25,7 +25,7 @@ module AdminSuite
|
|
|
25
25
|
refute LegacyExportableResource.instance_variable_defined?(:@export_formats)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
test "exportable warns once per resource class, naming the class and the 0.
|
|
28
|
+
test "exportable warns once per resource class, naming the class and the 0.6.0 removal" do
|
|
29
29
|
logged = []
|
|
30
30
|
LegacyExportableResource.stub(:warn_once_sink, ->(msg) { logged << msg }) do
|
|
31
31
|
2.times { LegacyExportableResource.exportable(:json, :csv) }
|
|
@@ -33,7 +33,15 @@ module AdminSuite
|
|
|
33
33
|
|
|
34
34
|
assert_equal 1, logged.size
|
|
35
35
|
assert_includes logged.first, "LegacyExportableResource"
|
|
36
|
-
|
|
36
|
+
# Deliberately a hardcoded literal, not read off
|
|
37
|
+
# EXPORTABLE_DEPRECATION_MESSAGE_FORMAT: reading the version out of
|
|
38
|
+
# the constant under test and asserting the message contains it is
|
|
39
|
+
# true by construction (format() only substitutes %<resource>s, never
|
|
40
|
+
# the version digits), so it can never fail on a wrong retarget --
|
|
41
|
+
# exactly the property this test exists to catch. If the removal
|
|
42
|
+
# target changes again, this literal must be updated by hand; that's
|
|
43
|
+
# the point.
|
|
44
|
+
assert_includes logged.first, "0.6.0"
|
|
37
45
|
end
|
|
38
46
|
end
|
|
39
47
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -43,14 +43,6 @@ unless defined?(ActiveRecord::Base)
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
module TurboFrameTestHelper
|
|
47
|
-
def turbo_frame_tag(name, **options, &block)
|
|
48
|
-
content_tag(:turbo_frame, capture(&block), id: name, **options)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
ActionView::Base.include(TurboFrameTestHelper)
|
|
53
|
-
|
|
54
46
|
module ReadOnlyResourceFixtures
|
|
55
47
|
class Relation
|
|
56
48
|
include Enumerable
|
|
@@ -142,3 +134,50 @@ module Admin
|
|
|
142
134
|
end
|
|
143
135
|
end
|
|
144
136
|
end
|
|
137
|
+
|
|
138
|
+
# The dummy app is database-free and `ActiveRecord::Base` above is a bare
|
|
139
|
+
# stub class, so every other fixture in this suite is a PORO and
|
|
140
|
+
# `active_record_base?` is false for all of them -- every AR-dependent path
|
|
141
|
+
# (`auto_admin_suite_path_for`, `format_table_cell`'s AR branch) is
|
|
142
|
+
# otherwise unreachable by tests. Subclassing the stub gives a fixture that
|
|
143
|
+
# genuinely satisfies `active_record_base?`, with no database and no
|
|
144
|
+
# railtie required. Established here (Task 3, phase 2b) because it's
|
|
145
|
+
# reused by later tasks (4, 7); those tasks' own test files each `require
|
|
146
|
+
# "test_helper"`, so this is visible to them even when a single test file
|
|
147
|
+
# is run in isolation via `rake test TEST=...` -- unlike a fixture defined
|
|
148
|
+
# only in association_linking_test.rb, which would not be.
|
|
149
|
+
module LinkingFixtures
|
|
150
|
+
class Company < ActiveRecord::Base
|
|
151
|
+
extend ActiveModel::Naming
|
|
152
|
+
|
|
153
|
+
attr_reader :id, :name
|
|
154
|
+
|
|
155
|
+
def initialize(id: 7, name: "Acme Corp")
|
|
156
|
+
@id = id
|
|
157
|
+
@name = name
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def self.all = ReadOnlyResourceFixtures::Relation.new([ new ])
|
|
161
|
+
def self.column_names = %w[id name]
|
|
162
|
+
def self.primary_key = "id"
|
|
163
|
+
def self.columns_hash = { "id" => Struct.new(:type).new(:integer) }
|
|
164
|
+
def self.find(_id) = new
|
|
165
|
+
def to_param = id.to_s
|
|
166
|
+
def attributes = { "id" => id, "name" => name }
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
module Admin
|
|
171
|
+
module Resources
|
|
172
|
+
# Registered so `auto_admin_suite_path_for` can resolve a real path for
|
|
173
|
+
# `LinkingFixtures::Company` instances (it looks up `registered_resources`
|
|
174
|
+
# by `model_class`). Never call `Admin::Base::Resource.reset_registry!` in
|
|
175
|
+
# a test: `inherited` fires only on class creation, so a reset-then-reload
|
|
176
|
+
# would permanently empty the registry for the rest of the run.
|
|
177
|
+
class LinkingCompanyResource < Admin::Base::Resource
|
|
178
|
+
model LinkingFixtures::Company
|
|
179
|
+
portal :ops
|
|
180
|
+
section :observability
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: admin_suite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- TechWright Labs
|
|
@@ -36,20 +36,40 @@ dependencies:
|
|
|
36
36
|
requirements:
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '9.0'
|
|
40
|
+
- - "<"
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '10'
|
|
43
|
+
type: :runtime
|
|
44
|
+
prerelease: false
|
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '9.0'
|
|
50
|
+
- - "<"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '10'
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: turbo-rails
|
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '2.0'
|
|
40
60
|
- - "<"
|
|
41
61
|
- !ruby/object:Gem::Version
|
|
42
|
-
version: '
|
|
62
|
+
version: '3.0'
|
|
43
63
|
type: :runtime
|
|
44
64
|
prerelease: false
|
|
45
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
46
66
|
requirements:
|
|
47
67
|
- - ">="
|
|
48
68
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: '
|
|
69
|
+
version: '2.0'
|
|
50
70
|
- - "<"
|
|
51
71
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: '
|
|
72
|
+
version: '3.0'
|
|
53
73
|
- !ruby/object:Gem::Dependency
|
|
54
74
|
name: lucide-rails
|
|
55
75
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -126,6 +146,7 @@ files:
|
|
|
126
146
|
- app/assets/builds/admin_suite_tailwind.css
|
|
127
147
|
- app/assets/rouge.css
|
|
128
148
|
- app/assets/tailwind/admin_suite.css
|
|
149
|
+
- app/assets/vendor/chart.umd.min.js
|
|
129
150
|
- app/assets/vendor/easymde.min.css
|
|
130
151
|
- app/assets/vendor/easymde.min.js
|
|
131
152
|
- app/controllers/admin_suite/application_controller.rb
|
|
@@ -139,6 +160,7 @@ files:
|
|
|
139
160
|
- app/helpers/admin_suite/resources_helper.rb
|
|
140
161
|
- app/helpers/admin_suite/theme_helper.rb
|
|
141
162
|
- app/javascript/admin_suite_application.js
|
|
163
|
+
- app/javascript/controllers/admin_suite/chart_controller.js
|
|
142
164
|
- app/javascript/controllers/admin_suite/click_actions_controller.js
|
|
143
165
|
- app/javascript/controllers/admin_suite/clipboard_controller.js
|
|
144
166
|
- app/javascript/controllers/admin_suite/code_editor_controller.js
|
|
@@ -260,15 +282,21 @@ files:
|
|
|
260
282
|
- test/dummy/public/robots.txt
|
|
261
283
|
- test/dummy/test/test_helper.rb
|
|
262
284
|
- test/fixtures/docs/progress/PROGRESS_REPORT.md
|
|
285
|
+
- test/integration/association_linking_test.rb
|
|
263
286
|
- test/integration/authentication_test.rb
|
|
264
287
|
- test/integration/authorization_test.rb
|
|
288
|
+
- test/integration/chart_panel_test.rb
|
|
265
289
|
- test/integration/dashboard_test.rb
|
|
266
290
|
- test/integration/docs_test.rb
|
|
291
|
+
- test/integration/index_table_test.rb
|
|
267
292
|
- test/integration/layout_assets_test.rb
|
|
268
293
|
- test/integration/navigation_sections_test.rb
|
|
269
294
|
- test/integration/pagination_and_stats_test.rb
|
|
270
295
|
- test/integration/read_only_resource_test.rb
|
|
296
|
+
- test/integration/searchable_select_search_test.rb
|
|
297
|
+
- test/integration/show_hide_blank_test.rb
|
|
271
298
|
- test/integration/theme_test.rb
|
|
299
|
+
- test/integration/toggle_test.rb
|
|
272
300
|
- test/lib/action_executor_redirect_test.rb
|
|
273
301
|
- test/lib/action_executor_test.rb
|
|
274
302
|
- test/lib/auth_http_basic_test.rb
|
|
@@ -278,6 +306,8 @@ files:
|
|
|
278
306
|
- test/lib/definition_loader_test.rb
|
|
279
307
|
- test/lib/engine_defaults_test.rb
|
|
280
308
|
- test/lib/form_field_renderer_test.rb
|
|
309
|
+
- test/lib/format_table_cell_test.rb
|
|
310
|
+
- test/lib/index_includes_test.rb
|
|
281
311
|
- test/lib/legacy_renderer_deprecation_test.rb
|
|
282
312
|
- test/lib/markdown_renderer_test.rb
|
|
283
313
|
- test/lib/renderer_test.rb
|