easy-admin-rails 0.2.6 → 0.2.7
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/app/assets/builds/easy_admin.base.js +7 -0
- data/app/assets/builds/easy_admin.base.js.map +2 -2
- data/app/assets/builds/easy_admin.css +207 -35
- data/app/components/easy_admin/fields/form/belongs_to_component.rb +0 -1
- data/app/components/easy_admin/form_layout_component.rb +553 -0
- data/app/components/easy_admin/permissions/user_role_permissions_component.rb +1 -3
- data/app/components/easy_admin/show_layout_component.rb +694 -24
- data/app/controllers/easy_admin/application_controller.rb +0 -5
- data/app/controllers/easy_admin/batch_actions_controller.rb +0 -1
- data/app/controllers/easy_admin/concerns/inline_field_editing.rb +4 -11
- data/app/controllers/easy_admin/concerns/resource_loading.rb +10 -9
- data/app/controllers/easy_admin/concerns/resource_pagination.rb +3 -0
- data/app/controllers/easy_admin/dashboards_controller.rb +0 -1
- data/app/controllers/easy_admin/resources_controller.rb +1 -5
- data/app/controllers/easy_admin/row_actions_controller.rb +1 -4
- data/app/helpers/easy_admin/fields_helper.rb +8 -22
- data/app/javascript/easy_admin/controllers/infinite_scroll_controller.js +12 -0
- data/app/views/easy_admin/resources/edit.html.erb +2 -2
- data/app/views/easy_admin/resources/new.html.erb +2 -2
- data/app/views/easy_admin/resources/show.html.erb +3 -1
- data/lib/easy_admin/field.rb +3 -2
- data/lib/easy_admin/layouts/builders/base_layout_builder.rb +245 -0
- data/lib/easy_admin/layouts/builders/form_layout_builder.rb +208 -0
- data/lib/easy_admin/layouts/builders/index_layout_builder.rb +22 -0
- data/lib/easy_admin/layouts/builders/show_layout_builder.rb +199 -0
- data/lib/easy_admin/layouts/dsl.rb +200 -0
- data/lib/easy_admin/layouts/layout_context.rb +189 -0
- data/lib/easy_admin/layouts/nodes/base_node.rb +88 -0
- data/lib/easy_admin/layouts/nodes/divider.rb +27 -0
- data/lib/easy_admin/layouts/nodes/field_node.rb +57 -0
- data/lib/easy_admin/layouts/nodes/grid.rb +60 -0
- data/lib/easy_admin/layouts/nodes/render_node.rb +41 -0
- data/lib/easy_admin/layouts/nodes/root.rb +25 -0
- data/lib/easy_admin/layouts/nodes/section.rb +46 -0
- data/lib/easy_admin/layouts/nodes/spacer.rb +17 -0
- data/lib/easy_admin/layouts/nodes/stubs.rb +109 -0
- data/lib/easy_admin/layouts/nodes/tab.rb +40 -0
- data/lib/easy_admin/layouts/nodes/tabs.rb +40 -0
- data/lib/easy_admin/layouts.rb +28 -0
- data/lib/easy_admin/permissions/resource_permissions.rb +1 -5
- data/lib/easy_admin/resource/base.rb +2 -2
- data/lib/easy_admin/resource/dsl.rb +2 -11
- data/lib/easy_admin/resource/field_registry.rb +58 -2
- data/lib/easy_admin/resource.rb +0 -9
- data/lib/easy_admin/resource_modules.rb +21 -4
- data/lib/easy_admin/version.rb +1 -1
- data/lib/generators/easy_admin/permissions/install_generator.rb +0 -10
- data/lib/generators/easy_admin/permissions/templates/migrations/create_permission_tables.rb +33 -3
- metadata +21 -9
- data/lib/easy_admin/resource/form_builder.rb +0 -123
- data/lib/easy_admin/resource/layout_builder.rb +0 -249
- data/lib/easy_admin/resource/show_builder.rb +0 -359
- data/lib/generators/easy_admin/permissions/templates/migrations/update_users_for_permissions.rb +0 -6
- data/lib/generators/easy_admin/rbac/rbac_generator.rb +0 -244
- data/lib/generators/easy_admin/rbac/templates/add_rbac_to_admin_users.rb +0 -23
- data/lib/generators/easy_admin/rbac/templates/super_admin.rb +0 -34
@@ -1,249 +0,0 @@
|
|
1
|
-
module EasyAdmin
|
2
|
-
module ResourceModules
|
3
|
-
# LayoutBuilder module for handling form and show layout configuration
|
4
|
-
# Manages form tabs and show page layout elements
|
5
|
-
module LayoutBuilder
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
class_attribute :form_tabs_config, :show_layout_config
|
10
|
-
|
11
|
-
def self.initialize_layout_builder
|
12
|
-
self.form_tabs_config = []
|
13
|
-
self.show_layout_config = []
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class_methods do
|
18
|
-
# Form tabs management
|
19
|
-
def add_form_tab(tab_config)
|
20
|
-
self.form_tabs_config = (self.form_tabs_config || []) + [tab_config]
|
21
|
-
end
|
22
|
-
|
23
|
-
def form_tabs
|
24
|
-
form_tabs_config
|
25
|
-
end
|
26
|
-
|
27
|
-
def has_form_tabs?
|
28
|
-
form_tabs_config.any?
|
29
|
-
end
|
30
|
-
|
31
|
-
def clear_form_tabs
|
32
|
-
self.form_tabs_config = []
|
33
|
-
end
|
34
|
-
|
35
|
-
# Show layout management
|
36
|
-
def add_show_layout_element(element_config)
|
37
|
-
self.show_layout_config = (self.show_layout_config || []) + [element_config]
|
38
|
-
end
|
39
|
-
|
40
|
-
def show_layout
|
41
|
-
show_layout_config
|
42
|
-
end
|
43
|
-
|
44
|
-
def has_show_layout?
|
45
|
-
show_layout_config.any?
|
46
|
-
end
|
47
|
-
|
48
|
-
def clear_show_layout
|
49
|
-
self.show_layout_config = []
|
50
|
-
end
|
51
|
-
|
52
|
-
# Form tab utilities
|
53
|
-
def find_form_tab(tab_name)
|
54
|
-
form_tabs_config.find { |tab| tab[:name].to_s == tab_name.to_s }
|
55
|
-
end
|
56
|
-
|
57
|
-
def form_tab_names
|
58
|
-
form_tabs_config.map { |tab| tab[:name] }
|
59
|
-
end
|
60
|
-
|
61
|
-
def form_tab_fields(tab_name)
|
62
|
-
tab = find_form_tab(tab_name)
|
63
|
-
tab ? tab[:fields] : []
|
64
|
-
end
|
65
|
-
|
66
|
-
def total_form_tabs_count
|
67
|
-
form_tabs_config.count
|
68
|
-
end
|
69
|
-
|
70
|
-
# Show layout utilities
|
71
|
-
def show_layout_rows
|
72
|
-
show_layout_config.select { |element| element[:type] == :row }
|
73
|
-
end
|
74
|
-
|
75
|
-
def show_layout_elements_count
|
76
|
-
count = 0
|
77
|
-
show_layout_config.each do |element|
|
78
|
-
count += count_nested_elements(element)
|
79
|
-
end
|
80
|
-
count
|
81
|
-
end
|
82
|
-
|
83
|
-
def find_show_layout_element(element_type)
|
84
|
-
find_element_in_layout(show_layout_config, element_type)
|
85
|
-
end
|
86
|
-
|
87
|
-
def has_show_layout_tabs?
|
88
|
-
find_show_layout_element(:tabs).present?
|
89
|
-
end
|
90
|
-
|
91
|
-
def has_show_layout_cards?
|
92
|
-
find_show_layout_element(:card).present?
|
93
|
-
end
|
94
|
-
|
95
|
-
def has_metric_cards?
|
96
|
-
find_show_layout_element(:metric_card).present?
|
97
|
-
end
|
98
|
-
|
99
|
-
def has_chart_cards?
|
100
|
-
find_show_layout_element(:chart_card).present?
|
101
|
-
end
|
102
|
-
|
103
|
-
# Layout validation
|
104
|
-
def validate_form_structure
|
105
|
-
errors = []
|
106
|
-
|
107
|
-
if has_form_tabs?
|
108
|
-
form_tabs_config.each_with_index do |tab, index|
|
109
|
-
unless tab[:name].present?
|
110
|
-
errors << "Form tab at index #{index} is missing a name"
|
111
|
-
end
|
112
|
-
|
113
|
-
unless tab[:fields].is_a?(Array)
|
114
|
-
errors << "Form tab '#{tab[:name]}' fields must be an array"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
errors
|
120
|
-
end
|
121
|
-
|
122
|
-
def validate_show_layout_structure
|
123
|
-
errors = []
|
124
|
-
|
125
|
-
show_layout_config.each_with_index do |element, index|
|
126
|
-
case element[:type]
|
127
|
-
when :row
|
128
|
-
unless element[:columns].is_a?(Array)
|
129
|
-
errors << "Row at index #{index} must have columns array"
|
130
|
-
end
|
131
|
-
|
132
|
-
if element[:columns].empty?
|
133
|
-
errors << "Row at index #{index} cannot have empty columns"
|
134
|
-
end
|
135
|
-
when :column
|
136
|
-
unless element[:elements].is_a?(Array)
|
137
|
-
errors << "Column at index #{index} must have elements array"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
errors
|
143
|
-
end
|
144
|
-
|
145
|
-
# Layout rebuild methods
|
146
|
-
def rebuild_form_from_fields
|
147
|
-
return if fields_config.empty?
|
148
|
-
|
149
|
-
# Create a default tab with all non-readonly fields
|
150
|
-
default_tab = {
|
151
|
-
name: "General",
|
152
|
-
label: "General",
|
153
|
-
icon: nil,
|
154
|
-
fields: fields_config.reject { |field| field[:readonly] }
|
155
|
-
}
|
156
|
-
|
157
|
-
self.form_tabs_config = [default_tab]
|
158
|
-
end
|
159
|
-
|
160
|
-
def rebuild_show_layout_from_fields
|
161
|
-
return if fields_config.empty?
|
162
|
-
|
163
|
-
# Create a simple single-column layout with all fields
|
164
|
-
row_config = {
|
165
|
-
type: :row,
|
166
|
-
columns_count: 1,
|
167
|
-
spacing: "medium",
|
168
|
-
columns: [{
|
169
|
-
type: :column,
|
170
|
-
size: 12,
|
171
|
-
elements: [{
|
172
|
-
type: :card,
|
173
|
-
title: "Details",
|
174
|
-
color: "light",
|
175
|
-
padding: "medium",
|
176
|
-
shadow: "small",
|
177
|
-
elements: fields_config.map { |field|
|
178
|
-
{
|
179
|
-
type: :field,
|
180
|
-
name: field[:name],
|
181
|
-
label: field[:label],
|
182
|
-
field_type: :default,
|
183
|
-
format: field[:format],
|
184
|
-
css_classes: nil,
|
185
|
-
show_label: true
|
186
|
-
}
|
187
|
-
}
|
188
|
-
}]
|
189
|
-
}]
|
190
|
-
}
|
191
|
-
|
192
|
-
self.show_layout_config = [row_config]
|
193
|
-
end
|
194
|
-
|
195
|
-
private
|
196
|
-
|
197
|
-
def count_nested_elements(element)
|
198
|
-
count = 1
|
199
|
-
|
200
|
-
case element[:type]
|
201
|
-
when :row
|
202
|
-
element[:columns]&.each { |column| count += count_nested_elements(column) }
|
203
|
-
when :column
|
204
|
-
element[:elements]&.each { |child| count += count_nested_elements(child) }
|
205
|
-
when :card
|
206
|
-
element[:elements]&.each { |child| count += count_nested_elements(child) }
|
207
|
-
when :tabs
|
208
|
-
element[:tabs]&.each { |tab| count += count_nested_elements(tab) }
|
209
|
-
when :tab
|
210
|
-
element[:elements]&.each { |child| count += count_nested_elements(child) }
|
211
|
-
end
|
212
|
-
|
213
|
-
count
|
214
|
-
end
|
215
|
-
|
216
|
-
def find_element_in_layout(layout, element_type)
|
217
|
-
layout.each do |element|
|
218
|
-
return element if element[:type] == element_type
|
219
|
-
|
220
|
-
case element[:type]
|
221
|
-
when :row
|
222
|
-
element[:columns]&.each do |column|
|
223
|
-
found = find_element_in_layout([column], element_type)
|
224
|
-
return found if found
|
225
|
-
end
|
226
|
-
when :column, :card
|
227
|
-
if element[:elements]
|
228
|
-
found = find_element_in_layout(element[:elements], element_type)
|
229
|
-
return found if found
|
230
|
-
end
|
231
|
-
when :tabs
|
232
|
-
element[:tabs]&.each do |tab|
|
233
|
-
found = find_element_in_layout([tab], element_type)
|
234
|
-
return found if found
|
235
|
-
end
|
236
|
-
when :tab
|
237
|
-
if element[:elements]
|
238
|
-
found = find_element_in_layout(element[:elements], element_type)
|
239
|
-
return found if found
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
nil
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
@@ -1,359 +0,0 @@
|
|
1
|
-
module EasyAdmin
|
2
|
-
module ResourceModules
|
3
|
-
# ShowBuilder class for show layout DSL
|
4
|
-
# Handles all show page layout definitions with rows, columns, cards, and tabs
|
5
|
-
class ShowBuilder
|
6
|
-
PREDEFINED_COLORS = %w[primary secondary success danger warning info light dark white transparent].freeze
|
7
|
-
COLUMN_SIZES = [1, 2, 3, 4, 6, 8, 12].freeze
|
8
|
-
SPACING_OPTIONS = %w[none small medium large].freeze
|
9
|
-
PADDING_OPTIONS = %w[none small medium large].freeze
|
10
|
-
HEADING_SIZES = %w[small medium large].freeze
|
11
|
-
DIVIDER_STYLES = %w[default dashed dotted thick].freeze
|
12
|
-
SHADOW_OPTIONS = %w[none small medium large].freeze
|
13
|
-
|
14
|
-
def initialize(resource_class)
|
15
|
-
@resource_class = resource_class
|
16
|
-
@context_stack = []
|
17
|
-
@current_row = nil
|
18
|
-
@current_column = nil
|
19
|
-
@current_card = nil
|
20
|
-
@current_tab_container = nil
|
21
|
-
@current_tab = nil
|
22
|
-
end
|
23
|
-
|
24
|
-
# Layout methods
|
25
|
-
def row(columns: 1, spacing: "medium", &block)
|
26
|
-
validate_spacing!(spacing)
|
27
|
-
|
28
|
-
row_config = {
|
29
|
-
type: :row,
|
30
|
-
columns_count: columns,
|
31
|
-
spacing: spacing,
|
32
|
-
columns: []
|
33
|
-
}
|
34
|
-
|
35
|
-
push_context
|
36
|
-
@current_row = row_config
|
37
|
-
|
38
|
-
if @current_column
|
39
|
-
@current_column[:elements] << row_config
|
40
|
-
else
|
41
|
-
@resource_class.add_show_layout_element(row_config)
|
42
|
-
end
|
43
|
-
|
44
|
-
instance_eval(&block) if block_given?
|
45
|
-
pop_context
|
46
|
-
end
|
47
|
-
|
48
|
-
def column(size: nil, &block)
|
49
|
-
raise "column must be called within a row block" unless @current_row
|
50
|
-
|
51
|
-
calculated_size = size || (12 / [@current_row[:columns_count], 1].max)
|
52
|
-
validate_column_size!(calculated_size)
|
53
|
-
|
54
|
-
column_config = {
|
55
|
-
type: :column,
|
56
|
-
size: calculated_size,
|
57
|
-
elements: []
|
58
|
-
}
|
59
|
-
|
60
|
-
push_context
|
61
|
-
@current_column = column_config
|
62
|
-
@current_row[:columns] << column_config
|
63
|
-
|
64
|
-
instance_eval(&block) if block_given?
|
65
|
-
pop_context
|
66
|
-
end
|
67
|
-
|
68
|
-
# Card methods
|
69
|
-
def card(title: nil, color: "light", padding: "medium", shadow: "small", &block)
|
70
|
-
raise "card must be called within a column block" unless @current_column
|
71
|
-
validate_color!(color)
|
72
|
-
validate_padding!(padding)
|
73
|
-
validate_shadow!(shadow)
|
74
|
-
|
75
|
-
card_config = {
|
76
|
-
type: :card,
|
77
|
-
title: title,
|
78
|
-
color: color,
|
79
|
-
padding: padding,
|
80
|
-
shadow: shadow,
|
81
|
-
elements: []
|
82
|
-
}
|
83
|
-
|
84
|
-
push_context
|
85
|
-
@current_card = card_config
|
86
|
-
@current_column[:elements] << card_config
|
87
|
-
|
88
|
-
instance_eval(&block) if block_given?
|
89
|
-
pop_context
|
90
|
-
end
|
91
|
-
|
92
|
-
def metric_card(title:, value:, color: "primary", icon: nil, trend: nil)
|
93
|
-
raise "metric_card must be called within a column block" unless @current_column
|
94
|
-
validate_color!(color)
|
95
|
-
|
96
|
-
metric_config = {
|
97
|
-
type: :metric_card,
|
98
|
-
title: title,
|
99
|
-
value: value,
|
100
|
-
icon: icon,
|
101
|
-
color: color,
|
102
|
-
trend: trend
|
103
|
-
}
|
104
|
-
|
105
|
-
@current_column[:elements] << metric_config
|
106
|
-
end
|
107
|
-
|
108
|
-
def chart_card(title:, chart_type:, **options, &block)
|
109
|
-
raise "chart_card must be called within a column block" unless @current_column
|
110
|
-
|
111
|
-
chart_config = {
|
112
|
-
type: :chart_card,
|
113
|
-
title: title,
|
114
|
-
chart_type: chart_type,
|
115
|
-
height: options[:height] || 350,
|
116
|
-
data_source: options[:data_source],
|
117
|
-
css_classes: options[:class] || "card",
|
118
|
-
config: {}
|
119
|
-
}
|
120
|
-
|
121
|
-
if block_given?
|
122
|
-
chart_builder = ChartBuilder.new
|
123
|
-
chart_builder.instance_eval(&block)
|
124
|
-
chart_config[:config] = chart_builder.config
|
125
|
-
end
|
126
|
-
|
127
|
-
@current_column[:elements] << chart_config
|
128
|
-
end
|
129
|
-
|
130
|
-
# Tab methods
|
131
|
-
def tabs(**options, &block)
|
132
|
-
container = @current_card || @current_column
|
133
|
-
raise "tabs must be called within a card or column block" unless container
|
134
|
-
|
135
|
-
tabs_config = {
|
136
|
-
type: :tabs,
|
137
|
-
css_classes: options[:class] || "tabs-menu",
|
138
|
-
tabs: []
|
139
|
-
}
|
140
|
-
|
141
|
-
push_context
|
142
|
-
@current_tab_container = tabs_config
|
143
|
-
container[:elements] << tabs_config
|
144
|
-
|
145
|
-
instance_eval(&block) if block_given?
|
146
|
-
pop_context
|
147
|
-
end
|
148
|
-
|
149
|
-
def tab(name, **options, &block)
|
150
|
-
raise "tab must be called within a tabs block" unless @current_tab_container
|
151
|
-
|
152
|
-
tab_config = {
|
153
|
-
name: name,
|
154
|
-
label: options[:label] || name,
|
155
|
-
icon: options[:icon],
|
156
|
-
active: options[:active] || false,
|
157
|
-
elements: []
|
158
|
-
}
|
159
|
-
|
160
|
-
push_context
|
161
|
-
@current_tab = tab_config
|
162
|
-
@current_tab_container[:tabs] << tab_config
|
163
|
-
|
164
|
-
instance_eval(&block) if block_given?
|
165
|
-
pop_context
|
166
|
-
end
|
167
|
-
|
168
|
-
# Field display methods
|
169
|
-
def field(name, **options)
|
170
|
-
container = @current_tab || @current_card || @current_column
|
171
|
-
raise "field must be called within a tab, card, or column block" unless container
|
172
|
-
|
173
|
-
label_value = if options.key?(:label) && options[:label] == false
|
174
|
-
nil
|
175
|
-
else
|
176
|
-
options[:label] || name.to_s.humanize
|
177
|
-
end
|
178
|
-
|
179
|
-
field_config = {
|
180
|
-
type: :field,
|
181
|
-
name: name,
|
182
|
-
label: label_value,
|
183
|
-
field_type: options[:field_type] || :default,
|
184
|
-
format: options[:format],
|
185
|
-
css_classes: options[:class],
|
186
|
-
show_label: options.fetch(:show_label, true)
|
187
|
-
}
|
188
|
-
|
189
|
-
container[:elements] << field_config
|
190
|
-
end
|
191
|
-
|
192
|
-
def fields(*field_names, **options)
|
193
|
-
field_names.each do |name|
|
194
|
-
field(name, **options)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
# Component rendering support with context
|
199
|
-
def render(component_class_or_instance, **options)
|
200
|
-
container = @current_tab || @current_card || @current_column
|
201
|
-
raise "render must be called within a tab, card, or column block" unless container
|
202
|
-
|
203
|
-
component_config = {
|
204
|
-
type: :custom_component,
|
205
|
-
component_class: component_class_or_instance.class,
|
206
|
-
component_options: options,
|
207
|
-
component_instance: component_class_or_instance
|
208
|
-
}
|
209
|
-
|
210
|
-
container[:elements] << component_config
|
211
|
-
component_class_or_instance
|
212
|
-
end
|
213
|
-
|
214
|
-
# Content methods
|
215
|
-
def content(html = nil, **options, &block)
|
216
|
-
container = @current_tab || @current_card || @current_column
|
217
|
-
raise "content must be called within a tab, card, or column block" unless container
|
218
|
-
|
219
|
-
content_config = {
|
220
|
-
type: :content,
|
221
|
-
html: html,
|
222
|
-
css_classes: options[:class],
|
223
|
-
block: block
|
224
|
-
}
|
225
|
-
|
226
|
-
container[:elements] << content_config
|
227
|
-
end
|
228
|
-
|
229
|
-
def heading(text, level: 2, size: "medium")
|
230
|
-
container = @current_tab || @current_card || @current_column
|
231
|
-
raise "heading must be called within a tab, card, or column block" unless container
|
232
|
-
|
233
|
-
validate_heading_level!(level)
|
234
|
-
validate_heading_size!(size)
|
235
|
-
|
236
|
-
heading_config = {
|
237
|
-
type: :heading,
|
238
|
-
text: text,
|
239
|
-
level: level,
|
240
|
-
size: size
|
241
|
-
}
|
242
|
-
|
243
|
-
container[:elements] << heading_config
|
244
|
-
end
|
245
|
-
|
246
|
-
def divider(style: "default")
|
247
|
-
container = @current_tab || @current_card || @current_column
|
248
|
-
raise "divider must be called within a tab, card, or column block" unless container
|
249
|
-
|
250
|
-
validate_divider_style!(style)
|
251
|
-
|
252
|
-
divider_config = {
|
253
|
-
type: :divider,
|
254
|
-
style: style
|
255
|
-
}
|
256
|
-
|
257
|
-
container[:elements] << divider_config
|
258
|
-
end
|
259
|
-
|
260
|
-
private
|
261
|
-
|
262
|
-
def validate_color!(color)
|
263
|
-
return if PREDEFINED_COLORS.include?(color.to_s)
|
264
|
-
raise ArgumentError, "Invalid color '#{color}'. Available colors: #{PREDEFINED_COLORS.join(', ')}"
|
265
|
-
end
|
266
|
-
|
267
|
-
def validate_column_size!(size)
|
268
|
-
return if COLUMN_SIZES.include?(size)
|
269
|
-
raise ArgumentError, "Invalid column size '#{size}'. Available sizes: #{COLUMN_SIZES.join(', ')}"
|
270
|
-
end
|
271
|
-
|
272
|
-
def validate_spacing!(spacing)
|
273
|
-
return if SPACING_OPTIONS.include?(spacing.to_s)
|
274
|
-
raise ArgumentError, "Invalid spacing '#{spacing}'. Available options: #{SPACING_OPTIONS.join(', ')}"
|
275
|
-
end
|
276
|
-
|
277
|
-
def validate_padding!(padding)
|
278
|
-
return if PADDING_OPTIONS.include?(padding.to_s)
|
279
|
-
raise ArgumentError, "Invalid padding '#{padding}'. Available options: #{PADDING_OPTIONS.join(', ')}"
|
280
|
-
end
|
281
|
-
|
282
|
-
def validate_shadow!(shadow)
|
283
|
-
return if SHADOW_OPTIONS.include?(shadow.to_s)
|
284
|
-
raise ArgumentError, "Invalid shadow '#{shadow}'. Available options: #{SHADOW_OPTIONS.join(', ')}"
|
285
|
-
end
|
286
|
-
|
287
|
-
def validate_heading_level!(level)
|
288
|
-
return if (1..6).include?(level)
|
289
|
-
raise ArgumentError, "Invalid heading level '#{level}'. Must be between 1 and 6"
|
290
|
-
end
|
291
|
-
|
292
|
-
def validate_heading_size!(size)
|
293
|
-
return if HEADING_SIZES.include?(size.to_s)
|
294
|
-
raise ArgumentError, "Invalid heading size '#{size}'. Available sizes: #{HEADING_SIZES.join(', ')}"
|
295
|
-
end
|
296
|
-
|
297
|
-
def validate_divider_style!(style)
|
298
|
-
return if DIVIDER_STYLES.include?(style.to_s)
|
299
|
-
raise ArgumentError, "Invalid divider style '#{style}'. Available styles: #{DIVIDER_STYLES.join(', ')}"
|
300
|
-
end
|
301
|
-
|
302
|
-
def push_context
|
303
|
-
@context_stack.push({
|
304
|
-
row: @current_row,
|
305
|
-
column: @current_column,
|
306
|
-
card: @current_card,
|
307
|
-
tab_container: @current_tab_container,
|
308
|
-
tab: @current_tab
|
309
|
-
})
|
310
|
-
end
|
311
|
-
|
312
|
-
def pop_context
|
313
|
-
if @context_stack.any?
|
314
|
-
context = @context_stack.pop
|
315
|
-
@current_row = context[:row]
|
316
|
-
@current_column = context[:column]
|
317
|
-
@current_card = context[:card]
|
318
|
-
@current_tab_container = context[:tab_container]
|
319
|
-
@current_tab = context[:tab]
|
320
|
-
else
|
321
|
-
@current_row = nil
|
322
|
-
@current_column = nil
|
323
|
-
@current_card = nil
|
324
|
-
@current_tab_container = nil
|
325
|
-
@current_tab = nil
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
# ChartBuilder class for chart configuration
|
331
|
-
class ChartBuilder
|
332
|
-
attr_reader :config
|
333
|
-
|
334
|
-
def initialize
|
335
|
-
@config = {}
|
336
|
-
end
|
337
|
-
|
338
|
-
def series(data)
|
339
|
-
@config[:series] = data
|
340
|
-
end
|
341
|
-
|
342
|
-
def categories(data)
|
343
|
-
@config[:categories] = data
|
344
|
-
end
|
345
|
-
|
346
|
-
def colors(data)
|
347
|
-
@config[:colors] = data
|
348
|
-
end
|
349
|
-
|
350
|
-
def title(text)
|
351
|
-
@config[:title] = text
|
352
|
-
end
|
353
|
-
|
354
|
-
def subtitle(text)
|
355
|
-
@config[:subtitle] = text
|
356
|
-
end
|
357
|
-
end
|
358
|
-
end
|
359
|
-
end
|
data/lib/generators/easy_admin/permissions/templates/migrations/update_users_for_permissions.rb
DELETED
@@ -1,6 +0,0 @@
|
|
1
|
-
class UpdateUsersForEasyAdminPermissions < ActiveRecord::Migration<%= migration_version %>
|
2
|
-
def change
|
3
|
-
add_column :<%= user_model_name.tableize %>, :permissions_cache, :json, default: {}, null: false
|
4
|
-
add_index :<%= user_model_name.tableize %>, :permissions_cache, using: :gin
|
5
|
-
end
|
6
|
-
end
|