admin_it 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|