admin_it 1.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rubocop.yml +5 -0
- data/.yardopts +3 -0
- data/Gemfile +5 -0
- data/README.md +58 -0
- data/README_RU.md +52 -0
- data/Rakefile +23 -0
- data/admin_it.gemspec +38 -0
- data/app/assets/fonts/admin_it/FontAwesome.otf +0 -0
- data/app/assets/fonts/admin_it/fontawesome-webfont.eot +0 -0
- data/app/assets/fonts/admin_it/fontawesome-webfont.svg +414 -0
- data/app/assets/fonts/admin_it/fontawesome-webfont.ttf +0 -0
- data/app/assets/fonts/admin_it/fontawesome-webfont.woff +0 -0
- data/app/assets/fonts/admin_it/glyphicons-halflings-regular.eot +0 -0
- data/app/assets/fonts/admin_it/glyphicons-halflings-regular.svg +229 -0
- data/app/assets/fonts/admin_it/glyphicons-halflings-regular.ttf +0 -0
- data/app/assets/fonts/admin_it/glyphicons-halflings-regular.woff +0 -0
- data/app/assets/javascript/admin_it/admin_it.js +89 -0
- data/app/assets/javascript/admin_it/bootstrap.min.js +6 -0
- data/app/assets/stylesheets/admin_it/admin_it.css +25 -0
- data/app/assets/stylesheets/admin_it/bootstrap-theme.min.css +7 -0
- data/app/assets/stylesheets/admin_it/bootstrap.min.css +7 -0
- data/app/assets/stylesheets/admin_it/font-awesome.min.css +4 -0
- data/app/views/admin_it/context/_table.html.slim +38 -0
- data/app/views/admin_it/context/_tiles.html.slim +23 -0
- data/app/views/admin_it/edit.html.slim +2 -0
- data/app/views/admin_it/new.html.slim +2 -0
- data/app/views/admin_it/shared/_child.html.slim +15 -0
- data/app/views/admin_it/shared/_fields.html.slim +19 -0
- data/app/views/admin_it/shared/_filters.html.slim +40 -0
- data/app/views/admin_it/shared/_form.html.slim +50 -0
- data/app/views/admin_it/shared/_pagination.html.slim +41 -0
- data/app/views/admin_it/shared/_toolbar.html.slim +30 -0
- data/app/views/admin_it/show.html.slim +6 -0
- data/app/views/admin_it/table.html.slim +2 -0
- data/app/views/admin_it/tiles.html.slim +2 -0
- data/app/views/layouts/admin_it.html.slim +37 -0
- data/app/views/layouts/admin_it_dialog.html.slim +8 -0
- data/config.ru +7 -0
- data/lib/admin_it/config.rb +24 -0
- data/lib/admin_it/context/collection_context.rb +239 -0
- data/lib/admin_it/context/context.rb +232 -0
- data/lib/admin_it/context/show_context.rb +45 -0
- data/lib/admin_it/context/single_context.rb +199 -0
- data/lib/admin_it/context/table_context.rb +66 -0
- data/lib/admin_it/context/tiles_context.rb +31 -0
- data/lib/admin_it/context.rb +6 -0
- data/lib/admin_it/controller.rb +42 -0
- data/lib/admin_it/data/active_record.rb +283 -0
- data/lib/admin_it/data/data_behavior.rb +18 -0
- data/lib/admin_it/data/hash.rb +27 -0
- data/lib/admin_it/data/object.rb +51 -0
- data/lib/admin_it/data.rb +24 -0
- data/lib/admin_it/definitions.rb +89 -0
- data/lib/admin_it/engine.rb +56 -0
- data/lib/admin_it/env.rb +37 -0
- data/lib/admin_it/errors.rb +5 -0
- data/lib/admin_it/field/field.rb +174 -0
- data/lib/admin_it/field.rb +1 -0
- data/lib/admin_it/filters/entity_filter.rb +4 -0
- data/lib/admin_it/filters/field_filter.rb +31 -0
- data/lib/admin_it/filters/filter.rb +150 -0
- data/lib/admin_it/filters/value_filter.rb +52 -0
- data/lib/admin_it/filters.rb +4 -0
- data/lib/admin_it/helpers/field.rb +25 -0
- data/lib/admin_it/helpers/input.rb +22 -0
- data/lib/admin_it/helpers/page.rb +26 -0
- data/lib/admin_it/helpers/table.rb +85 -0
- data/lib/admin_it/helpers/tiles.rb +17 -0
- data/lib/admin_it/helpers/toolbar.rb +40 -0
- data/lib/admin_it/helpers/top_menu.rb +39 -0
- data/lib/admin_it/helpers.rb +12 -0
- data/lib/admin_it/locales/en.yml +14 -0
- data/lib/admin_it/locales/ru.yml +14 -0
- data/lib/admin_it/renderable.rb +18 -0
- data/lib/admin_it/resource.rb +292 -0
- data/lib/admin_it/utils.rb +21 -0
- data/lib/admin_it/version.rb +5 -0
- data/lib/admin_it.rb +19 -0
- data/lib/extend_it/array_of.rb +181 -0
- data/lib/extend_it/asserts.rb +38 -0
- data/lib/extend_it/callbacks.rb +105 -0
- data/lib/extend_it/caller.rb +35 -0
- data/lib/extend_it/class.rb +47 -0
- data/lib/extend_it/dsl.rb +94 -0
- data/lib/extend_it/refines.rb +6 -0
- data/lib/extend_it/symbolize.rb +39 -0
- data/lib/extend_it.rb +5 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +3 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/lib/context/collection_context_spec.rb +20 -0
- data/spec/lib/context/context_spec.rb +28 -0
- data/spec/lib/context/single_context_spec.rb +26 -0
- data/spec/lib/data/object_spec.rb +29 -0
- data/spec/lib/definitions_spec.rb +171 -0
- data/spec/lib/field_spec.rb +62 -0
- data/spec/lib/resource_spec.rb +39 -0
- data/spec/lib/utils_spec.rb +39 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/example_groups/context_example_group.rb +50 -0
- data/spec/support/shared_examples/context.rb +2 -0
- metadata +337 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title Admin
|
5
|
+
meta charset="utf-8"
|
6
|
+
= csrf_meta_tags
|
7
|
+
|
8
|
+
= stylesheet_link_tag 'admin_it/bootstrap.min', \
|
9
|
+
media: 'all', \
|
10
|
+
'data-turbolinks-track' => true
|
11
|
+
= stylesheet_link_tag 'admin_it/font-awesome.min', \
|
12
|
+
media: 'all', \
|
13
|
+
'data-turbolinks-track' => true
|
14
|
+
= stylesheet_link_tag 'admin_it/admin_it', \
|
15
|
+
media: 'all', \
|
16
|
+
'data-turbolinks-track' => true
|
17
|
+
= javascript_include_tag 'jquery', 'jquery_ujs', 'turbolinks'
|
18
|
+
= javascript_include_tag 'admin_it/bootstrap.min', \
|
19
|
+
'data-turbolinks-track' => true
|
20
|
+
= javascript_include_tag 'admin_it/admin_it'
|
21
|
+
|
22
|
+
- html = capture do
|
23
|
+
body style="padding-top: 70px"
|
24
|
+
nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"
|
25
|
+
div class="container"
|
26
|
+
<!-- top-menu -->
|
27
|
+
|
28
|
+
div class="container"
|
29
|
+
= render File.join(%w(admin_it shared toolbar))
|
30
|
+
= render File.join(%w(admin_it shared filters))
|
31
|
+
= yield
|
32
|
+
|
33
|
+
- top_menu_html = capture { context.top_menu.render }
|
34
|
+
- toolbar_html = capture { context.toolbar.render }
|
35
|
+
= html.gsub('<!-- top-menu -->', top_menu_html) \
|
36
|
+
.gsub('<!-- toolbar -->', toolbar_html) \
|
37
|
+
.html_safe
|
data/config.ru
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module AdminIt
|
2
|
+
module Config
|
3
|
+
def self.root
|
4
|
+
@root ||= Rails.root.join('app', 'admin_it')
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.root=(value)
|
8
|
+
value = File.expand_path(value, Rails.root)
|
9
|
+
fail ArgumentError unless File.directory?(value)
|
10
|
+
@root = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.controller
|
14
|
+
@controller ||= ActionController::Base
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.controller=(value)
|
18
|
+
unless value <= ActionController::Base
|
19
|
+
fail ArgumentError, 'Wrong controller'
|
20
|
+
end
|
21
|
+
@controller = value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
require 'json'
|
2
|
+
require File.join %w(extend_it symbolize)
|
3
|
+
|
4
|
+
using ExtendIt::Symbolize
|
5
|
+
|
6
|
+
module AdminIt
|
7
|
+
class CollectionContext < Context
|
8
|
+
extend FiltersHolder
|
9
|
+
|
10
|
+
@entities_getter = nil
|
11
|
+
|
12
|
+
class << self
|
13
|
+
dsl_block :entities
|
14
|
+
dsl_accessor :default_sorting
|
15
|
+
dsl_use_hash :filters
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.before_configure
|
19
|
+
return if resource.nil?
|
20
|
+
visible = fields(scope: :visible).map(&:field_name)
|
21
|
+
@filters = Hash[
|
22
|
+
resource.filters
|
23
|
+
.select { |f| f <= FieldFilter }
|
24
|
+
.select { |f| visible.include?(f.field.field_name) }
|
25
|
+
.map { |f| [f.filter_name, f] }
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.filter(name, filter_class: nil, &block)
|
30
|
+
assert_symbol(:name)
|
31
|
+
if @filters.key?(name)
|
32
|
+
filter = @filters[name] = Class.new(@filters[name]) if block_given?
|
33
|
+
else
|
34
|
+
filter_class = Filter if filter_class.nil? || !filter_class <= Filter
|
35
|
+
filter = @filters[name] = filter_class.create(name, self)
|
36
|
+
end
|
37
|
+
filter.instance_eval(&block) if block_given?
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.entities_getter
|
41
|
+
@entities
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.collection?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.path
|
49
|
+
AdminIt::Engine.routes.url_helpers.send("#{resource.plural}_path")
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.sortable_fields(*names)
|
53
|
+
names = names.ensure_symbols
|
54
|
+
fields.each do |_field|
|
55
|
+
_field.sortable = names.include?(_field.field_name)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
attr_accessor :entity
|
60
|
+
class_attr_reader :entities_getter, :path
|
61
|
+
|
62
|
+
before_load do |store: {}, params: {}|
|
63
|
+
self.sorting = store[:sorting] || self.class.default_sorting
|
64
|
+
self.sorting = params[:sorting] if params.key?(:sorting)
|
65
|
+
self.filters = store[:filters] || []
|
66
|
+
self.filters = params[:filters] if params.key?(:filters)
|
67
|
+
end
|
68
|
+
|
69
|
+
after_load do |store: {}, params: {}|
|
70
|
+
self.active_filter = params[:active_filter] || store[:active_filter]
|
71
|
+
end
|
72
|
+
|
73
|
+
before_save do |params: {}|
|
74
|
+
params.merge!(sorting: sorting.join(';'))
|
75
|
+
params.merge!(filters: filters.map { |f| f.dump }.join(';'))
|
76
|
+
unless active_filter.nil?
|
77
|
+
params.merge!(active_filter: active_filter.name.to_s)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def sorting
|
82
|
+
return @sorting unless @sorting.nil?
|
83
|
+
self.sorting = self.class.default_sorting
|
84
|
+
end
|
85
|
+
|
86
|
+
def sorting=(value)
|
87
|
+
value = value.to_s if value.is_a?(Symbol)
|
88
|
+
if value.is_a?(Array)
|
89
|
+
@sorting = value
|
90
|
+
elsif value.is_a?(String) && !value.empty?
|
91
|
+
@sorting = [] unless /\W[+\-]\w/ =~ value
|
92
|
+
@sorting ||= []
|
93
|
+
sortable = self.class.fields(scope: :sortable).map(&:field_name)
|
94
|
+
value.split(/[;,|]/).each do |sort|
|
95
|
+
sort.strip!
|
96
|
+
if sort[0] == '-'
|
97
|
+
sort = sort[1..-1] + ':'
|
98
|
+
@sorting.delete_if { |s| s.index(sort) == 0 }
|
99
|
+
else
|
100
|
+
sort = sort[1..-1] if sort[0] == '+'
|
101
|
+
sort, order = sort.split(':')
|
102
|
+
order = 'asc' if order != 'desc'
|
103
|
+
sort = sort.to_sym
|
104
|
+
@sorting << "#{sort}:#{order}" if sortable.include?(sort)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
else
|
108
|
+
@sorting = []
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def all_filters
|
113
|
+
self.class.filters
|
114
|
+
end
|
115
|
+
|
116
|
+
def filters
|
117
|
+
(@filters ||= {}).values
|
118
|
+
end
|
119
|
+
|
120
|
+
def filters=(value)
|
121
|
+
if value.is_a?(Array)
|
122
|
+
@filters = Hash[
|
123
|
+
value.select { |f| f.is_a?(Filter) }.map { |f| [f.name, f] }
|
124
|
+
]
|
125
|
+
elsif value.is_a?(Hash)
|
126
|
+
self.filters = value.values
|
127
|
+
elsif value.is_a?(String)
|
128
|
+
@filters ||= {}
|
129
|
+
value.strip!
|
130
|
+
@filters = {} if value.empty?
|
131
|
+
value.split(/[;|]/).each do |str|
|
132
|
+
str.strip!
|
133
|
+
remove = str[0] == '-'
|
134
|
+
str = str[1..-1] if remove
|
135
|
+
m = Filter::REGEXP.match(str)
|
136
|
+
next if m.nil?
|
137
|
+
if remove
|
138
|
+
@filters.delete(m[:name].to_sym)
|
139
|
+
else
|
140
|
+
name = m[:name].to_sym
|
141
|
+
if @filters.key?(name)
|
142
|
+
@filters[name].change(m[:params])
|
143
|
+
else
|
144
|
+
@filters[name] = Filter.load(str, self.class.filters)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
else
|
149
|
+
@filters = {}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def active_filter
|
154
|
+
@active_filter ||= filters.empty? ? nil : filters.first
|
155
|
+
end
|
156
|
+
|
157
|
+
def active_filter=(value)
|
158
|
+
if value.nil?
|
159
|
+
active_filter
|
160
|
+
elsif value.is_a?(Class) && value <= Filter
|
161
|
+
@active_filter = value
|
162
|
+
elsif value.is_a?(String)
|
163
|
+
value = value.to_sym
|
164
|
+
@active_filter = filters.find { |f| f.name == value }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def sortable_fields
|
169
|
+
@sortable_fields ||= fields(scope: :sortable)
|
170
|
+
end
|
171
|
+
|
172
|
+
def sortable
|
173
|
+
@sortable ||= sortable_fields.map(&:name)
|
174
|
+
end
|
175
|
+
|
176
|
+
def load_context
|
177
|
+
collection =
|
178
|
+
if entities_getter.nil?
|
179
|
+
if controller.respond_to?("#{resource.name}_entities")
|
180
|
+
controller.send("#{resource.name}_entities", name)
|
181
|
+
elsif controller.respond_to?(:entities)
|
182
|
+
controller.entities(entity_class, name)
|
183
|
+
else
|
184
|
+
load_entities
|
185
|
+
end
|
186
|
+
else
|
187
|
+
entities_getter.call
|
188
|
+
end
|
189
|
+
filters.each do |filter|
|
190
|
+
collection = filter.apply(collection)
|
191
|
+
end
|
192
|
+
self.entities = collection
|
193
|
+
end
|
194
|
+
|
195
|
+
def entities=(value)
|
196
|
+
@entities = value
|
197
|
+
end
|
198
|
+
|
199
|
+
def entities
|
200
|
+
self.entity = nil
|
201
|
+
collection = self
|
202
|
+
@enumerator ||= Enumerator.new do |yielder|
|
203
|
+
@entities.each do |v|
|
204
|
+
collection.entity = v
|
205
|
+
yielder << v
|
206
|
+
end
|
207
|
+
collection.entity = nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def count
|
212
|
+
return @count unless @count.nil?
|
213
|
+
# apply filters and limits first
|
214
|
+
entities if @enumerator.nil?
|
215
|
+
# if @count is not setted yet - calculate it
|
216
|
+
@count = entities.count
|
217
|
+
end
|
218
|
+
|
219
|
+
protected
|
220
|
+
|
221
|
+
def load_entities
|
222
|
+
[]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
class ListContext < CollectionContext
|
227
|
+
def self.path
|
228
|
+
AdminIt::Engine.routes.url_helpers.send("list_#{resource.plural}_path")
|
229
|
+
end
|
230
|
+
|
231
|
+
class << self
|
232
|
+
protected
|
233
|
+
|
234
|
+
def default_icon
|
235
|
+
'bars'
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require File.join %w(extend_it dsl)
|
3
|
+
require File.join %w(extend_it array_of)
|
4
|
+
require File.join %w(extend_it symbolize)
|
5
|
+
|
6
|
+
using ExtendIt::Symbolize
|
7
|
+
|
8
|
+
module AdminIt
|
9
|
+
class Context
|
10
|
+
extend ExtendIt::Class
|
11
|
+
extend ExtendIt::Dsl
|
12
|
+
include ExtendIt::Callbacks
|
13
|
+
extend DataBehavior
|
14
|
+
extend FieldsHolder
|
15
|
+
|
16
|
+
class << self
|
17
|
+
extend ExtendIt::Dsl
|
18
|
+
|
19
|
+
attr_reader :context_name
|
20
|
+
attr_accessor :controller_class
|
21
|
+
|
22
|
+
dsl_accessor :icon do |value|
|
23
|
+
value.nil? ? default_icon : value.to_s
|
24
|
+
end
|
25
|
+
dsl_use_hash :fields
|
26
|
+
end
|
27
|
+
|
28
|
+
inherited_class_reader :resource, :entity_class
|
29
|
+
define_callbacks :initialize, :load, :save
|
30
|
+
|
31
|
+
def self.create(context_name, _resource, &block)
|
32
|
+
fail ArgumentError, 'Wrong resource' unless _resource.is_a?(Resource)
|
33
|
+
base = self
|
34
|
+
Class.new(base) do
|
35
|
+
@resource = _resource
|
36
|
+
@context_name = context_name
|
37
|
+
@entity_class = @resource.entity_class
|
38
|
+
|
39
|
+
import_data_module(base)
|
40
|
+
|
41
|
+
@fields = Hash[
|
42
|
+
_resource.fields(scope: :all).map { |f| [f.field_name, f] }
|
43
|
+
]
|
44
|
+
|
45
|
+
before_configure if respond_to?(:before_configure)
|
46
|
+
instance_eval(&block) if block_given?
|
47
|
+
after_configure if respond_to?(:after_configure)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.field(*names, field_class: nil, &block)
|
52
|
+
names.ensure_symbols.each do |name|
|
53
|
+
if @fields.key?(name)
|
54
|
+
field = @fields[name] = Class.new(@fields[name]) if block_given?
|
55
|
+
else
|
56
|
+
field_class = Field if field_class.nil? || !field_class <= Field
|
57
|
+
field = @fields[name] = field_class.create(name, entity_class)
|
58
|
+
end
|
59
|
+
field.instance_eval(&block) if block_given?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.collection?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.single?
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.entity_path?
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.url(context = nil, **params)
|
76
|
+
url = context.nil? ? path : context.path
|
77
|
+
params = context.nil? ? params : context.url_params(**params)
|
78
|
+
unless params.empty?
|
79
|
+
url << '?' << params.map { |k, v| "#{k}=#{v}" }.join('&')
|
80
|
+
url = URI.escape(url)
|
81
|
+
end
|
82
|
+
url
|
83
|
+
end
|
84
|
+
|
85
|
+
class << self
|
86
|
+
protected
|
87
|
+
|
88
|
+
def default_icon
|
89
|
+
''
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class_attr_reader :collection?, :single?, :entity_class, :resource, :icon,
|
94
|
+
:entity_path?
|
95
|
+
attr_reader :top_menu, :toolbar, :parent, :template, :controller
|
96
|
+
|
97
|
+
CONTEXT_REGEXP = /\A
|
98
|
+
(?<resource_name>[a-zA-Z_][a-zA-Z_0-9]*)\/
|
99
|
+
(?<context_name>[a-zA-Z_][a-zA-Z_0-9]*)
|
100
|
+
(\((?<identity_value>[a-zA-Z_0-9]+)\))?
|
101
|
+
\z/x
|
102
|
+
|
103
|
+
def initialize(from, params: nil, store: nil, parent_init: false)
|
104
|
+
run_callbacks :initialize do
|
105
|
+
if from.is_a?(self.class.controller_class)
|
106
|
+
@controller = from
|
107
|
+
elsif from.is_a?(Context)
|
108
|
+
@controller = from.controller
|
109
|
+
self.parent = from unless parent_init == true
|
110
|
+
params ||= {}
|
111
|
+
store ||= {}
|
112
|
+
end
|
113
|
+
|
114
|
+
@fields = self.class.fields(scope: :all).map { |f| f.new }
|
115
|
+
|
116
|
+
if store.nil?
|
117
|
+
session = controller.session
|
118
|
+
store = session[:admin_it] ||= {}
|
119
|
+
store = store[resource.name] ||= {}
|
120
|
+
store = store[name] ||= {}
|
121
|
+
end
|
122
|
+
|
123
|
+
if params.nil?
|
124
|
+
params = controller.request.query_parameters
|
125
|
+
end
|
126
|
+
params = Hash[params.map { |k, v| [k.to_sym, v] }]
|
127
|
+
|
128
|
+
run_callbacks :load, arguments: { params: params, store: store } do
|
129
|
+
load_context unless parent_init == true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
after_load do |store: {}, params: {}|
|
135
|
+
self.layout = params[:layout] if params.key?(:layout)
|
136
|
+
if params.key?(:parent)
|
137
|
+
self.parent = params[:parent]
|
138
|
+
elsif store.key?(:parent)
|
139
|
+
self.parent = store[:parent]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def name
|
144
|
+
@name ||= self.class.context_name
|
145
|
+
end
|
146
|
+
|
147
|
+
def field(name)
|
148
|
+
@fields.find { |f| f.name == name }
|
149
|
+
end
|
150
|
+
|
151
|
+
def fields(scope: :visible)
|
152
|
+
case scope
|
153
|
+
when nil, :all then @fields
|
154
|
+
when :visible then @fields.select { |f| f.visible? }
|
155
|
+
when :hidden then @fields.select { |f| !f.visible? }
|
156
|
+
when :readable then @fields.select { |f| f.readable? }
|
157
|
+
when :writable then @fields.select { |f| f.writable? }
|
158
|
+
when Field::TYPES then @fields.select { |f| f.type == scope }
|
159
|
+
else @fields
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def save(**params)
|
164
|
+
return if controller.nil?
|
165
|
+
session = controller.session
|
166
|
+
store = session[:admin_it] ||= {}
|
167
|
+
store = store[resource.name] ||= {}
|
168
|
+
run_callbacks :save, arguments: [{ params: params }] do
|
169
|
+
store[name] = params
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def layout
|
174
|
+
@layout ||= ''
|
175
|
+
end
|
176
|
+
|
177
|
+
def layout=(value)
|
178
|
+
value = value.to_sym if value.is_a?(String)
|
179
|
+
return unless value.is_a?(Symbol)
|
180
|
+
@layout = case value
|
181
|
+
when :dialog then 'dialog'
|
182
|
+
else ''
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def parent=(value)
|
187
|
+
return if value.nil?
|
188
|
+
if value.is_a?(Context)
|
189
|
+
@parent = value
|
190
|
+
elsif value.is_a?(String)
|
191
|
+
m = CONTEXT_REGEXP.match(value)
|
192
|
+
unless m.nil?
|
193
|
+
r = AdminIt.resources[m[:resource_name].downcase.to_sym]
|
194
|
+
return if r.nil?
|
195
|
+
c = r[m[:context_name].downcase.to_sym]
|
196
|
+
return if c.nil?
|
197
|
+
@parent = c.new(self, parent_init: true)
|
198
|
+
unless m[:identity_value].nil?
|
199
|
+
@parent.entity = @parent.load_entity(identity: m[:identity_value])
|
200
|
+
end
|
201
|
+
end
|
202
|
+
else
|
203
|
+
@parent = nil
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def child?
|
208
|
+
parent.is_a?(Context)
|
209
|
+
end
|
210
|
+
|
211
|
+
def begin_render(template)
|
212
|
+
@template = template
|
213
|
+
@toolbar = Helpers::Toolbar.new(template)
|
214
|
+
@top_menu = Helpers::TopMenu.new(template, class: 'navbar-nav')
|
215
|
+
end
|
216
|
+
|
217
|
+
def url_params(**params)
|
218
|
+
unless @parent.nil?
|
219
|
+
params.merge!(parent: @parent.send(:context_param))
|
220
|
+
end
|
221
|
+
params
|
222
|
+
end
|
223
|
+
|
224
|
+
protected
|
225
|
+
|
226
|
+
def context_param
|
227
|
+
"#{resource.name}/#{name}"
|
228
|
+
end
|
229
|
+
|
230
|
+
def load_context; end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module AdminIt
|
2
|
+
class ShowContext < SingleContext
|
3
|
+
include Identifiable
|
4
|
+
|
5
|
+
class << self
|
6
|
+
include Renderable
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def default_icon
|
11
|
+
'info-circle'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.entity_path?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.read(entity = nil, &block)
|
20
|
+
if entity.nil?
|
21
|
+
@reader = block if block_given?
|
22
|
+
elsif !@reader.nil?
|
23
|
+
@reader.call(entity)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy_entity
|
28
|
+
if entity_destroyer.nil?
|
29
|
+
if controller.respond_to?("#{resource.name}_destroy")
|
30
|
+
controller.send("#{resource.name}_destroy")
|
31
|
+
elsif controller.respond_to?(:destroy_entity)
|
32
|
+
controller.destroy_entity(entity_class)
|
33
|
+
else
|
34
|
+
destroy
|
35
|
+
end
|
36
|
+
else
|
37
|
+
entity_destroyer.call(controller)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def destroy; end
|
44
|
+
end
|
45
|
+
end
|