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,199 @@
|
|
1
|
+
require File.join %w(extend_it dsl)
|
2
|
+
require File.join %w(extend_it symbolize)
|
3
|
+
|
4
|
+
using ExtendIt::Symbolize
|
5
|
+
|
6
|
+
module AdminIt
|
7
|
+
class Section
|
8
|
+
extend ExtendIt::Dsl
|
9
|
+
include Renderable
|
10
|
+
dsl_accessor :name, :display_name
|
11
|
+
dsl_boolean :visible
|
12
|
+
# dsl_block :render_context
|
13
|
+
def fields(*names)
|
14
|
+
names.empty? ? @fields ||= [] : @fields = names
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Identifiable
|
19
|
+
def self.included(base)
|
20
|
+
base.extend(ClassMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
def identity; end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def context_param
|
28
|
+
identity.nil? ? super : "#{super}(#{identity})"
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class SingleContext < Context
|
36
|
+
class << self
|
37
|
+
dsl_block :entity_getter, :entity_saver, :entity_destroyer
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.sections
|
41
|
+
(@sections ||= {}).values
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.section(*names, &block)
|
45
|
+
@sections ||= {}
|
46
|
+
names.ensure_symbols.each do |name|
|
47
|
+
if @sections.key?(name)
|
48
|
+
section = @sections[name]
|
49
|
+
else
|
50
|
+
if @sections.empty?
|
51
|
+
general = Section.new
|
52
|
+
general.name(:general)
|
53
|
+
# TODO: require this and other files after I18n config in engine.rb
|
54
|
+
#general.display_name(I18n.t('admin_it.collection.no_data'))
|
55
|
+
general.display_name('Основные свойства')
|
56
|
+
general.fields(*fields.map(&:field_name))
|
57
|
+
@sections[:general] = general
|
58
|
+
end
|
59
|
+
section = Section.new
|
60
|
+
section.name(name)
|
61
|
+
@sections[name] = section
|
62
|
+
end
|
63
|
+
section.instance_eval(&block) if block_given?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.single?
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.path(entity)
|
72
|
+
AdminIt::Engine.routes.url_helpers.send(
|
73
|
+
"#{resource.name}_path",
|
74
|
+
entity
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
class_attr_reader :entity_getter, :entity_saver, :entity_destroyer, :sections
|
79
|
+
attr_accessor :entity
|
80
|
+
|
81
|
+
after_load do |store: {}, params: {}|
|
82
|
+
self.section = params[:section] || store[:section]
|
83
|
+
end
|
84
|
+
|
85
|
+
before_save do |params: {}|
|
86
|
+
params.merge!(section: section)
|
87
|
+
end
|
88
|
+
|
89
|
+
def values
|
90
|
+
return {} if @entity.nil?
|
91
|
+
Hash[fields(scope: :readable).map { |f| [f.name, f.read(@entity)] }]
|
92
|
+
end
|
93
|
+
|
94
|
+
def path(_entity: nil)
|
95
|
+
_entity ||= entity
|
96
|
+
self.class.path(_entity)
|
97
|
+
end
|
98
|
+
|
99
|
+
def section
|
100
|
+
@section ||= sections.empty? ? :none : :general
|
101
|
+
end
|
102
|
+
|
103
|
+
def section=(value)
|
104
|
+
value = value.downcase.to_sym if value.is_a?(String)
|
105
|
+
return unless value.is_a?(Symbol)
|
106
|
+
if sections.empty?
|
107
|
+
return if section != :none
|
108
|
+
else
|
109
|
+
return unless sections.map(&:name).include?(value)
|
110
|
+
end
|
111
|
+
@section = section
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
def load_context
|
117
|
+
self.entity =
|
118
|
+
if entity_getter.nil?
|
119
|
+
getter = "#{resource.name}_#{name}_entity".to_sym
|
120
|
+
if controller.respond_to?(getter)
|
121
|
+
controller.send(getter)
|
122
|
+
else
|
123
|
+
getter = "#{name}_entity"
|
124
|
+
if controller.respond_to?(getter)
|
125
|
+
controller.send(getter, entity_class)
|
126
|
+
else
|
127
|
+
load_entity
|
128
|
+
end
|
129
|
+
end
|
130
|
+
else
|
131
|
+
entity_getter.call(controller.params)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def load_entity(identity: nil)
|
136
|
+
[]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class SavableSingleContext < SingleContext
|
141
|
+
def self.save_action; end
|
142
|
+
|
143
|
+
def save_entity
|
144
|
+
if entity_saver.nil?
|
145
|
+
if controller.respond_to?("#{resource.name}_save")
|
146
|
+
controller.send("#{resource.name}_save", name)
|
147
|
+
elsif controller.respond_to?(:save)
|
148
|
+
controller.save(entity_class, name)
|
149
|
+
else
|
150
|
+
save_entity
|
151
|
+
end
|
152
|
+
else
|
153
|
+
entity_saver.call(controller, name)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class_attr_reader :save_action
|
158
|
+
|
159
|
+
protected
|
160
|
+
|
161
|
+
def save_entity; end
|
162
|
+
end
|
163
|
+
|
164
|
+
class EditContext < SavableSingleContext
|
165
|
+
include Identifiable
|
166
|
+
|
167
|
+
def self.path(entity)
|
168
|
+
AdminIt::Engine.routes.url_helpers.send(
|
169
|
+
"edit_#{resource.name}_path", entity
|
170
|
+
)
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.save_action
|
174
|
+
:update
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.entity_path?
|
178
|
+
true
|
179
|
+
end
|
180
|
+
|
181
|
+
class << self
|
182
|
+
protected
|
183
|
+
|
184
|
+
def default_icon
|
185
|
+
'pencil'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class NewContext < SavableSingleContext
|
191
|
+
def self.path
|
192
|
+
AdminIt::Engine.routes.url_helpers.send("new_#{resource.name}_path")
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.save_action
|
196
|
+
:create
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.join %w(extend_it dsl)
|
2
|
+
|
3
|
+
module AdminIt
|
4
|
+
class TableContext < CollectionContext
|
5
|
+
class << self
|
6
|
+
dsl_accessor :page_size, default: 10 do |value|
|
7
|
+
value.is_a?(Fixnum) && value > 0 ? value : 10
|
8
|
+
end
|
9
|
+
|
10
|
+
dsl_boolean :actions
|
11
|
+
|
12
|
+
dsl_block :row
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def default_icon
|
17
|
+
'table'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.path
|
22
|
+
AdminIt::Engine.routes
|
23
|
+
.url_helpers.send("table_#{resource.plural}_path")
|
24
|
+
end
|
25
|
+
|
26
|
+
class_attr_reader :page_size, :actions?
|
27
|
+
|
28
|
+
after_load do |store: {}, params: {}|
|
29
|
+
self.page = params[:page] || store[:page]
|
30
|
+
end
|
31
|
+
|
32
|
+
before_save do |params: {}|
|
33
|
+
params.merge!(page: page)
|
34
|
+
end
|
35
|
+
|
36
|
+
def pages
|
37
|
+
@pages ||= (count.to_f / page_size).ceil
|
38
|
+
end
|
39
|
+
|
40
|
+
def page
|
41
|
+
@page ||= 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def page=(value)
|
45
|
+
if value.is_a?(String)
|
46
|
+
value = case value.downcase
|
47
|
+
when 'next' then page + 1
|
48
|
+
when 'prev', 'previous' then page - 1
|
49
|
+
when 'first' then 1
|
50
|
+
when 'last' then pages
|
51
|
+
else value.to_i
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if value.is_a?(Fixnum) && value > 0 && value <= pages
|
55
|
+
# reset entities enumerator if page changed
|
56
|
+
@enumerator = nil if !@enumerator.nil? && value != @page
|
57
|
+
@page = value
|
58
|
+
end
|
59
|
+
@page ||= 1
|
60
|
+
end
|
61
|
+
|
62
|
+
def headers
|
63
|
+
Hash[fields.map { |f| [f.name, f.display_name] }]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.join %w(extend_it dsl)
|
2
|
+
|
3
|
+
module AdminIt
|
4
|
+
class TilesContext < CollectionContext
|
5
|
+
class << self
|
6
|
+
dsl_accessor :header do |value|
|
7
|
+
if value.nil?
|
8
|
+
fields.empty? ? nil : fields.first.name
|
9
|
+
else
|
10
|
+
field = fields.find { |f| f.field_name == value }
|
11
|
+
field.nil? ? header(nil) : field.field_name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.path
|
17
|
+
AdminIt::Engine.routes
|
18
|
+
.url_helpers.send("tiles_#{resource.plural}_path")
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
protected
|
23
|
+
|
24
|
+
def default_icon
|
25
|
+
'th'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class_attr_reader :header
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.join %w(admin_it context context)
|
2
|
+
require File.join %w(admin_it context single_context)
|
3
|
+
require File.join %w(admin_it context collection_context)
|
4
|
+
require File.join %w(admin_it context table_context)
|
5
|
+
require File.join %w(admin_it context tiles_context)
|
6
|
+
require File.join %w(admin_it context show_context)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module AdminIt
|
2
|
+
module Controller
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
attr_reader :context
|
6
|
+
helper_method :context, :resource
|
7
|
+
helper AdminIt::Helpers
|
8
|
+
helper AdminIt::Engine.routes.url_helpers
|
9
|
+
|
10
|
+
if AdminIt::Env.pundit?
|
11
|
+
collections = @resource.collections.map(&:context_name)
|
12
|
+
after_action :verify_authorized, except: collections
|
13
|
+
after_action :verify_policy_scoped, only: collections
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def resource
|
19
|
+
self.class.instance_variable_get(:@resource)
|
20
|
+
end
|
21
|
+
|
22
|
+
def redirect_to_default
|
23
|
+
redirect_to(resource[resource.default_context].path)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def load_context(context_class)
|
29
|
+
@context = context_class.new(self)
|
30
|
+
yield if block_given?
|
31
|
+
layout = ['admin_it', params[:layout]].compact.join('_')
|
32
|
+
if !performed?
|
33
|
+
if layout == 'admin_it' && !request.query_parameters.empty?
|
34
|
+
redirect_to request.path
|
35
|
+
else
|
36
|
+
render template: "admin_it/#{context.name}", layout: layout
|
37
|
+
end
|
38
|
+
end
|
39
|
+
@context.save
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
require File.join %w(extend_it class)
|
2
|
+
|
3
|
+
module AdminIt
|
4
|
+
module ActiveRecordData
|
5
|
+
module Resource
|
6
|
+
def display_name
|
7
|
+
entity_class
|
8
|
+
.model_name
|
9
|
+
.human#(count: 0)
|
10
|
+
.split(' ')
|
11
|
+
.map { |s| s.mb_chars.capitalize }
|
12
|
+
.join(' ')
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def default_fields(&block)
|
18
|
+
enum = Enumerator.new do |yielder|
|
19
|
+
exclude = []
|
20
|
+
entity_class.reflections.each do |name, a|
|
21
|
+
f = AdminIt::Field.create(name, entity_class, type: :relation)
|
22
|
+
f.assoc = a
|
23
|
+
yielder << f
|
24
|
+
exclude << "#{name}_id" if a.belongs_to?
|
25
|
+
end
|
26
|
+
entity_class.columns_hash.each do |name, c|
|
27
|
+
next if exclude.include?(name)
|
28
|
+
name = name.to_sym
|
29
|
+
opts = { type: c.type }
|
30
|
+
if name == :id
|
31
|
+
opts[:visible] = false
|
32
|
+
opts[:writable] = false
|
33
|
+
end
|
34
|
+
yielder << AdminIt::Field.create(name, entity_class, opts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
block_given? ? enum.each(&block) : enum
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_filters
|
41
|
+
enum = Enumerator.new do |yielder|
|
42
|
+
fields.each do |field|
|
43
|
+
next if field.type == :relation
|
44
|
+
name = "#{field.field_name}_value"
|
45
|
+
yielder << AdminIt::ValueFilter.create(name, self, field)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
block_given? ? enum.each(&block) : enum
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module CollectionContext
|
53
|
+
def entities=(value)
|
54
|
+
super(value)
|
55
|
+
@count = value.count
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def load_entities
|
61
|
+
collection =
|
62
|
+
if AdminIt::Env.pundit?
|
63
|
+
controller.policy_scope(entity_class)
|
64
|
+
else
|
65
|
+
entity_class.all
|
66
|
+
end
|
67
|
+
if child?
|
68
|
+
collection = collection.where(parent.resource.name => parent.entity)
|
69
|
+
end
|
70
|
+
sort = {}
|
71
|
+
sorting.each do |_sort|
|
72
|
+
name, order = _sort.split(':')
|
73
|
+
sort[name.to_sym] = order.to_sym
|
74
|
+
end
|
75
|
+
collection = collection.order(sort) unless sort.empty?
|
76
|
+
collection
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module SingleContext
|
81
|
+
protected
|
82
|
+
|
83
|
+
def load_entity(identity: nil)
|
84
|
+
identity ||= controller.params[:id]
|
85
|
+
entity = entity_class.find(identity)
|
86
|
+
if AdminIt::Env.pundit?
|
87
|
+
controller.authorize(entity, "#{name}?")
|
88
|
+
end
|
89
|
+
if child?
|
90
|
+
fields
|
91
|
+
.select { |f| f.type == :relation &&
|
92
|
+
f.assoc.klass == parent.entity_class }
|
93
|
+
.each do |f|
|
94
|
+
if f.assoc.collection?
|
95
|
+
entity.send(f.name) << parent.entity
|
96
|
+
else
|
97
|
+
entity.send("#{f.name}=", parent.entity)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
entity
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
module SavableSingleContext
|
106
|
+
protected
|
107
|
+
|
108
|
+
def save_entity
|
109
|
+
if AdminIt::Env.pundit?
|
110
|
+
controller.authorize(entity, "#{self.class.save_action}?")
|
111
|
+
end
|
112
|
+
params = controller.params[resource.name]
|
113
|
+
fields(scope: :writable).each do |field|
|
114
|
+
next unless params.key?(field.name)
|
115
|
+
next unless field.writable?
|
116
|
+
next if field.type == :relation
|
117
|
+
field.write(entity, params[field.name])
|
118
|
+
end
|
119
|
+
if entity.save
|
120
|
+
controller.redirect_to_default
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_child_context(for_resource, context_class: :table)
|
125
|
+
child_resource = AdminIt.resources[for_resource]
|
126
|
+
return nil if child_resource.nil?
|
127
|
+
child_resource[context_class].new(self)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
module NewContext
|
132
|
+
def self.included(base)
|
133
|
+
base.after_initialize do
|
134
|
+
if child?
|
135
|
+
fields
|
136
|
+
.select { |f| f.type == :relation &&
|
137
|
+
f.assoc.klass == parent.entity_class }
|
138
|
+
.each do |f|
|
139
|
+
if f.assoc.collection?
|
140
|
+
entity.send(f.name) << parent.entity
|
141
|
+
else
|
142
|
+
entity.send("#{f.name}=", parent.entity)
|
143
|
+
end
|
144
|
+
f.visible = false
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
protected
|
151
|
+
|
152
|
+
def load_entity(identity: nil)
|
153
|
+
entity = entity_class.new
|
154
|
+
if AdminIt::Env.pundit?
|
155
|
+
controller.authorize(entity, "#{name}?")
|
156
|
+
end
|
157
|
+
entity
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module ShowContext
|
162
|
+
def identity
|
163
|
+
entity.id
|
164
|
+
end
|
165
|
+
|
166
|
+
protected
|
167
|
+
|
168
|
+
def destroy
|
169
|
+
if AdminIt::Env.pundit?
|
170
|
+
controller.authorize(entity, :destroy?)
|
171
|
+
end
|
172
|
+
if entity.destroy
|
173
|
+
controller.redirect_to_default
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
module EditContext
|
179
|
+
def identity
|
180
|
+
entity.id
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
module TableContext
|
185
|
+
def entities
|
186
|
+
if @entities.count > page_size
|
187
|
+
# limit collection to current page
|
188
|
+
@entities = @entities
|
189
|
+
.offset(page_size * (page - 1))
|
190
|
+
.limit(page_size)
|
191
|
+
end
|
192
|
+
super
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
module Field
|
197
|
+
def self.included(base)
|
198
|
+
base.class_eval do
|
199
|
+
class << self
|
200
|
+
attr_accessor :assoc
|
201
|
+
|
202
|
+
protected
|
203
|
+
|
204
|
+
def default_display_name
|
205
|
+
entity_class.human_attribute_name(field_name)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
class_attr_reader :assoc
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
protected
|
213
|
+
|
214
|
+
def read_value(entity)
|
215
|
+
value = entity.send(name)
|
216
|
+
if type == :relation
|
217
|
+
assoc.collection? ? value.map(&:id).to_json : value.id
|
218
|
+
else
|
219
|
+
value
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def show_value(entity)
|
224
|
+
value = entity.send(name)
|
225
|
+
if type == :relation
|
226
|
+
resource = AdminIt.resources.values.find do |r|
|
227
|
+
r.entity_class == assoc.klass
|
228
|
+
end
|
229
|
+
return I18n.t('admin_it.relation.no_resource') if resource.nil?
|
230
|
+
context = resource.contexts.find { |c| c <= ShowContext }
|
231
|
+
return I18n.t('admin_it.relation.no_context') if context.nil?
|
232
|
+
if assoc.collection?
|
233
|
+
if value.count == 0
|
234
|
+
I18n.t('admin_it.collection.no_data')
|
235
|
+
else
|
236
|
+
context.read(value.first) + ' ...'
|
237
|
+
end
|
238
|
+
else
|
239
|
+
context.read(value)
|
240
|
+
end
|
241
|
+
else
|
242
|
+
value
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def write_value(entity, value)
|
247
|
+
entity.send("#{name}=", value)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
module ValueFilter
|
252
|
+
def all_values(collection = nil, &block)
|
253
|
+
enum = Enumerator.new do |yielder|
|
254
|
+
field
|
255
|
+
.entity_class
|
256
|
+
.select(self.class.field.field_name)
|
257
|
+
.group(self.class.field.field_name)
|
258
|
+
.count
|
259
|
+
.each do |v, c|
|
260
|
+
yielder << { value: v, count: c }
|
261
|
+
end
|
262
|
+
end
|
263
|
+
block_given? ? enum.each(&block) : enum
|
264
|
+
end
|
265
|
+
|
266
|
+
def apply(collection)
|
267
|
+
return collection if @values.empty?
|
268
|
+
binding = []
|
269
|
+
conditions = ''
|
270
|
+
if @values.size == 1 && @values[0].nil?
|
271
|
+
conditions = "#{field.field_name} IS NULL"
|
272
|
+
else
|
273
|
+
conditions = "#{field.field_name} IN (?)"
|
274
|
+
binding << @values.select { |v| !v.nil? }
|
275
|
+
if @values.any? { |v| v.nil? }
|
276
|
+
conditions += " OR #{field.field_name} IS NULL"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
collection = collection.where(conditions, *binding)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module AdminIt
|
2
|
+
module DataBehavior
|
3
|
+
private
|
4
|
+
|
5
|
+
def import_data_module(base)
|
6
|
+
@data_module = AdminIt.data_module(@entity_class)
|
7
|
+
return unless @data_module.is_a?(Module)
|
8
|
+
parents.reverse.each do |mod|
|
9
|
+
next if mod.name.nil?
|
10
|
+
begin
|
11
|
+
import_module = @data_module.const_get(mod.name.split('::').last)
|
12
|
+
include(import_module) if import_module.is_a?(Module)
|
13
|
+
rescue NameError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module AdminIt
|
2
|
+
module HashData
|
3
|
+
module Context
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def load_fields
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Field
|
16
|
+
protected
|
17
|
+
|
18
|
+
def read_value(entity)
|
19
|
+
entity[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def write_value(entity, value)
|
23
|
+
entity[name] = value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|