rear 0.2.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 +15 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +20 -0
- data/LICENSE +19 -0
- data/README.md +101 -0
- data/Rakefile +79 -0
- data/assets/api.js +307 -0
- data/assets/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css +8 -0
- data/assets/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js +26 -0
- data/assets/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/assets/bootstrap/css/bootstrap.min.css +9 -0
- data/assets/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/assets/bootstrap/img/glyphicons-halflings.png +0 -0
- data/assets/bootstrap/js/bootstrap.min.js +6 -0
- data/assets/jquery.js +5 -0
- data/assets/noty/jquery.noty.js +520 -0
- data/assets/noty/layouts/top.js +34 -0
- data/assets/noty/layouts/topRight.js +43 -0
- data/assets/noty/promise.js +432 -0
- data/assets/noty/themes/default.js +156 -0
- data/assets/select2-bootstrap.css +86 -0
- data/assets/select2/select2-spinner.gif +0 -0
- data/assets/select2/select2.css +652 -0
- data/assets/select2/select2.min.js +22 -0
- data/assets/select2/select2.png +0 -0
- data/assets/select2/select2x2.png +0 -0
- data/assets/ui.css +75 -0
- data/assets/xhr.js +4 -0
- data/bin/rear +65 -0
- data/docs/Assocs.md +100 -0
- data/docs/Columns.md +404 -0
- data/docs/Deploy.md +62 -0
- data/docs/FileManager.md +75 -0
- data/docs/Filters.md +341 -0
- data/docs/Setup.md +201 -0
- data/lib/rear.rb +13 -0
- data/lib/rear/actions.rb +98 -0
- data/lib/rear/constants.rb +61 -0
- data/lib/rear/controller_setup.rb +249 -0
- data/lib/rear/helpers.rb +17 -0
- data/lib/rear/helpers/class.rb +46 -0
- data/lib/rear/helpers/columns.rb +68 -0
- data/lib/rear/helpers/filters.rb +147 -0
- data/lib/rear/helpers/generic.rb +73 -0
- data/lib/rear/helpers/order.rb +47 -0
- data/lib/rear/helpers/pager.rb +35 -0
- data/lib/rear/helpers/render.rb +37 -0
- data/lib/rear/home_controller.rb +10 -0
- data/lib/rear/input.rb +341 -0
- data/lib/rear/orm.rb +73 -0
- data/lib/rear/rear.rb +74 -0
- data/lib/rear/setup.rb +9 -0
- data/lib/rear/setup/associations.rb +33 -0
- data/lib/rear/setup/columns.rb +109 -0
- data/lib/rear/setup/filters.rb +314 -0
- data/lib/rear/setup/generic.rb +59 -0
- data/lib/rear/setup/menu.rb +39 -0
- data/lib/rear/templates/editor/ace.slim +7 -0
- data/lib/rear/templates/editor/assocs.slim +10 -0
- data/lib/rear/templates/editor/boolean.slim +5 -0
- data/lib/rear/templates/editor/bulk_edit.slim +75 -0
- data/lib/rear/templates/editor/checkbox.slim +5 -0
- data/lib/rear/templates/editor/ckeditor.slim +7 -0
- data/lib/rear/templates/editor/date.slim +9 -0
- data/lib/rear/templates/editor/datetime.slim +9 -0
- data/lib/rear/templates/editor/layout.slim +103 -0
- data/lib/rear/templates/editor/password.slim +1 -0
- data/lib/rear/templates/editor/radio.slim +5 -0
- data/lib/rear/templates/editor/select.slim +3 -0
- data/lib/rear/templates/editor/string.slim +1 -0
- data/lib/rear/templates/editor/text.slim +1 -0
- data/lib/rear/templates/editor/time.slim +9 -0
- data/lib/rear/templates/error.slim +36 -0
- data/lib/rear/templates/filters/boolean.slim +10 -0
- data/lib/rear/templates/filters/checkbox.slim +15 -0
- data/lib/rear/templates/filters/date.slim +10 -0
- data/lib/rear/templates/filters/datetime.slim +10 -0
- data/lib/rear/templates/filters/layout.slim +26 -0
- data/lib/rear/templates/filters/radio.slim +14 -0
- data/lib/rear/templates/filters/select.slim +9 -0
- data/lib/rear/templates/filters/string.slim +3 -0
- data/lib/rear/templates/filters/text.slim +3 -0
- data/lib/rear/templates/filters/time.slim +10 -0
- data/lib/rear/templates/home.slim +0 -0
- data/lib/rear/templates/layout.slim +78 -0
- data/lib/rear/templates/pager.slim +22 -0
- data/lib/rear/templates/pane/ace.slim +2 -0
- data/lib/rear/templates/pane/assocs.slim +62 -0
- data/lib/rear/templates/pane/boolean.slim +2 -0
- data/lib/rear/templates/pane/checkbox.slim +5 -0
- data/lib/rear/templates/pane/ckeditor.slim +2 -0
- data/lib/rear/templates/pane/date.slim +2 -0
- data/lib/rear/templates/pane/datetime.slim +2 -0
- data/lib/rear/templates/pane/layout.slim +111 -0
- data/lib/rear/templates/pane/password.slim +2 -0
- data/lib/rear/templates/pane/quickview.slim +21 -0
- data/lib/rear/templates/pane/radio.slim +5 -0
- data/lib/rear/templates/pane/select.slim +5 -0
- data/lib/rear/templates/pane/string.slim +2 -0
- data/lib/rear/templates/pane/text.slim +2 -0
- data/lib/rear/templates/pane/time.slim +2 -0
- data/lib/rear/utils.rb +288 -0
- data/rear.gemspec +27 -0
- data/test/helpers.rb +33 -0
- data/test/models/ar.rb +52 -0
- data/test/models/dm.rb +53 -0
- data/test/models/sq.rb +58 -0
- data/test/setup.rb +4 -0
- data/test/templates/adhoc/book/editor/name.slim +1 -0
- data/test/templates/adhoc/book/editor/string.slim +1 -0
- data/test/templates/adhoc/book/pane/name.slim +1 -0
- data/test/templates/adhoc/book/pane/string.slim +1 -0
- data/test/templates/shared/shared-templates/editor/string.slim +1 -0
- data/test/templates/shared/shared-templates/pane/string.slim +1 -0
- data/test/test__assocs.rb +249 -0
- data/test/test__columns.rb +269 -0
- data/test/test__crud.rb +81 -0
- data/test/test__custom_templates.rb +147 -0
- data/test/test__filters.rb +228 -0
- metadata +220 -0
data/lib/rear/helpers.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module ClassMixin
|
|
3
|
+
include RearConstants
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
module InstanceMixin
|
|
7
|
+
include RearConstants
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require 'rear/helpers/class'
|
|
12
|
+
require 'rear/helpers/columns'
|
|
13
|
+
require 'rear/helpers/filters'
|
|
14
|
+
require 'rear/helpers/generic'
|
|
15
|
+
require 'rear/helpers/order'
|
|
16
|
+
require 'rear/helpers/pager'
|
|
17
|
+
require 'rear/helpers/render'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module ClassMixin
|
|
3
|
+
|
|
4
|
+
def default_label
|
|
5
|
+
@__rear__default_label ||= self.name.gsub(/\W/, '_').freeze
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def menu_group?; @__rear__menu_group end
|
|
9
|
+
def readonly?; @__rear__readonly end
|
|
10
|
+
|
|
11
|
+
def orm
|
|
12
|
+
@__rear__orm
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def assocs
|
|
16
|
+
@__rear__managed_assocs ||= (@__rear__assocs || {}).inject({}) do |map,(type,assocs)|
|
|
17
|
+
map.merge type => assocs.reject {|assoc,*| ignored_assocs.include? assoc}
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# keeps the list of "real" columns as well as "virtual" ones.
|
|
22
|
+
# virtual refers to columns displayed on pane/editor pages
|
|
23
|
+
# but does exists in db
|
|
24
|
+
def columns
|
|
25
|
+
@__rear__columns ||= []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# keeps the list of columns that "physically" exists in db
|
|
29
|
+
def real_columns
|
|
30
|
+
@__rear__real_columns || []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def filters
|
|
34
|
+
mounted? ? @__rear__filters || {} : @__rear__filters ||= {}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def quick_filters
|
|
38
|
+
mounted? ? @__rear__quick_filters || {} : @__rear__quick_filters ||= {}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def internal_filters
|
|
42
|
+
mounted? ? @__rear__internal_filters || [] : @__rear__internal_filters ||= []
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module InstanceMixin
|
|
3
|
+
|
|
4
|
+
def pane_columns
|
|
5
|
+
@__rear__pane_columns ||= begin
|
|
6
|
+
pane_columns = columns.select {|c| c.pane?}
|
|
7
|
+
[RearInput.new(pkey)] + case action_name
|
|
8
|
+
when :reverse_assoc
|
|
9
|
+
(assoc_columns = __rear__.assoc_columns) ?
|
|
10
|
+
pane_columns.select {|c| assoc_columns.include? c.name} :
|
|
11
|
+
pane_columns[0..1]
|
|
12
|
+
when :quickview
|
|
13
|
+
pane_columns[0..0]
|
|
14
|
+
else
|
|
15
|
+
pane_columns
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def editor_columns
|
|
21
|
+
@__rear__editor_columns ||= columns.select {|c| c.editor?}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def columns
|
|
25
|
+
@__rear__columns ||= __rear__.columns.inject([]) do |columns,(name, type, attrs, proc)|
|
|
26
|
+
columns << RearInput.new(name, type, attrs, @brand_new_item, &proc)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def attrs column, scope
|
|
31
|
+
meth = '%s_attrs' % scope
|
|
32
|
+
column_attrs = column.send(meth)
|
|
33
|
+
return column_attrs if column_attrs.any?
|
|
34
|
+
__rear__.send(meth)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def render_pane_column column
|
|
38
|
+
render_column column, :pane
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def render_editor_column column
|
|
42
|
+
render_column column, :editor
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def render_column column, scope
|
|
46
|
+
template, value = %w[template value].map {|m| column.send('%s_%s' % [scope, m])}
|
|
47
|
+
locals = if column.optioned?
|
|
48
|
+
options = column.options
|
|
49
|
+
options = Hash[options.zip(options)] if options.is_a?(Array)
|
|
50
|
+
active_options = self.instance_exec(&column.active_options)
|
|
51
|
+
active_options = [active_options] unless active_options.is_a?(Array)
|
|
52
|
+
{options: options, active_options: active_options}
|
|
53
|
+
else
|
|
54
|
+
{value: self.instance_exec(&value)}
|
|
55
|
+
end
|
|
56
|
+
template.is_a?(Proc) ?
|
|
57
|
+
self.instance_exec(&template) :
|
|
58
|
+
render_slim_p(locals) { template_cache(path_to_rear_templates template) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def sortable_column? column
|
|
62
|
+
if column.name == pkey || column.order_by? ||
|
|
63
|
+
__rear__.real_columns.any? {|(n,t)| n == column.name}
|
|
64
|
+
sortable_vector column
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module InstanceMixin
|
|
3
|
+
|
|
4
|
+
def filters
|
|
5
|
+
__rear__.filters
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def quick_filters
|
|
9
|
+
__rear__.quick_filters
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def opted_quick_filters
|
|
13
|
+
@__rear__opted_quick_filters ||= begin
|
|
14
|
+
given_filters = params[:quick_filters] || {}
|
|
15
|
+
quick_filters.inject({}) do |map,(column,*)|
|
|
16
|
+
(v = given_filters[column.to_s]) && v.size > 0 ? map.merge(column => v) : map
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def quick_filter? column
|
|
22
|
+
opted_quick_filters[column]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# turn
|
|
26
|
+
# {'date' => {'gte' => 'foo', 'lte' => 'bar'}}
|
|
27
|
+
# into
|
|
28
|
+
# {
|
|
29
|
+
# :date => {
|
|
30
|
+
# :gte => ['foo', ['%s >= ?', '%s'] ],
|
|
31
|
+
# :lte => ['bar', ['%s <= ?', '%s'] ],
|
|
32
|
+
# }
|
|
33
|
+
# }
|
|
34
|
+
def opted_filters
|
|
35
|
+
@__rear__opted_filters ||= (params[:filters]||{}).inject({}) do |map,s|
|
|
36
|
+
(column = s.first) && (filter = filters[(column = column.to_sym)]).is_a?(Hash) &&
|
|
37
|
+
(setup = s.last).is_a?(Hash) && setup.each_pair do |cmp,v|
|
|
38
|
+
v && v.size > 0 && (query_formats = filters_query_map[(cmp=cmp.to_sym)]) &&
|
|
39
|
+
(filter_setup = filter[cmp]) && (map[column] ||= {})[cmp] = [
|
|
40
|
+
v, # do not typecast to Fixnum cause this will break Hash to query_string conversion
|
|
41
|
+
query_formats,
|
|
42
|
+
filter_setup,
|
|
43
|
+
]
|
|
44
|
+
end
|
|
45
|
+
map
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def filters_query_map
|
|
50
|
+
@@__rear__filters__query_map ||= FILTERS__QUERY_MAP.call(__rear__.orm)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def filter name, comparison_function = FILTERS__DECORATIVE_CMP
|
|
54
|
+
((opted_filters[name] || {})[comparison_function] || []).first
|
|
55
|
+
end
|
|
56
|
+
alias filter? filter
|
|
57
|
+
alias decorative_filter? filter
|
|
58
|
+
|
|
59
|
+
def filters_to_sql
|
|
60
|
+
conditions, sql_chunks, values = {}, [], []
|
|
61
|
+
|
|
62
|
+
quick_filters.each_pair do |column,filters|
|
|
63
|
+
next unless label = opted_quick_filters[column]
|
|
64
|
+
filters.each_pair do |filter,(query_formats,value)|
|
|
65
|
+
next unless label == filter
|
|
66
|
+
sql_chunks << query_formats.first % RearUtils.quote_column(model, column)
|
|
67
|
+
values << ([TrueClass, FalseClass, Regexp].include?(value.class) ? value : query_formats.last % value)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
opted_filters.each_pair do |column, setups|
|
|
72
|
+
setups.each_pair do |cmp, (value, query_formats, filter_setup)|
|
|
73
|
+
next if filter_setup[:decorative?]
|
|
74
|
+
|
|
75
|
+
sql_chunk = query_formats.first % RearUtils.quote_column(model, column)
|
|
76
|
+
custom_sql_chunk = nil
|
|
77
|
+
|
|
78
|
+
if filter_setup[:type] == :boolean && FILTERS__STR_TO_BOOLEAN.has_key?(value)
|
|
79
|
+
values << FILTERS__STR_TO_BOOLEAN[value]
|
|
80
|
+
else
|
|
81
|
+
case cmp
|
|
82
|
+
when :in
|
|
83
|
+
values << value
|
|
84
|
+
when :csl # comma separated list
|
|
85
|
+
values << value.to_s.split(',')
|
|
86
|
+
else
|
|
87
|
+
if value.is_a?(Array)
|
|
88
|
+
custom_sql_chunk = []
|
|
89
|
+
value.each do |v|
|
|
90
|
+
custom_sql_chunk << sql_chunk
|
|
91
|
+
values << query_formats.last % v
|
|
92
|
+
end
|
|
93
|
+
custom_sql_chunk = '(' + custom_sql_chunk.join(' OR ') + ')'
|
|
94
|
+
else
|
|
95
|
+
values << query_formats.last % value
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
sql_chunks << (custom_sql_chunk || sql_chunk)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
__rear__.internal_filters.each do |m|
|
|
104
|
+
next unless items = self.send(m)
|
|
105
|
+
sql_chunks << filters_query_map[:in].first % pkey
|
|
106
|
+
values << items.map {|i| i[pkey]}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
sql_chunks.any? ?
|
|
110
|
+
conditions.merge(conditions: [sql_chunks.join(' AND '), *values]) :
|
|
111
|
+
conditions
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def render_filters
|
|
115
|
+
html = assets_mapper(route(:assets), suffix: '-rear').js_tag('xhr')
|
|
116
|
+
main_filters = filters.inject(html) do |html,(column,setups)|
|
|
117
|
+
setups.each_pair do |comparison_function, setup|
|
|
118
|
+
context = {
|
|
119
|
+
name: 'filters[%s][%s]' % [column, comparison_function],
|
|
120
|
+
column: column,
|
|
121
|
+
value: filter(column, comparison_function),
|
|
122
|
+
setup: setup,
|
|
123
|
+
attrs: Hash[setup[:attrs]]
|
|
124
|
+
}
|
|
125
|
+
template = template_cache(path_to_rear_templates(setup[:template]))
|
|
126
|
+
html << render_slim_p(context) { template }
|
|
127
|
+
end
|
|
128
|
+
html << ' '
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def filter_setup_to_options(setup)
|
|
133
|
+
options = setup[:proc] ? self.instance_exec(&setup[:proc]) : {}
|
|
134
|
+
if options.is_a?(Array)
|
|
135
|
+
options.flatten!
|
|
136
|
+
options = Hash[options.zip(options)]
|
|
137
|
+
end
|
|
138
|
+
return options if options.is_a?(Hash)
|
|
139
|
+
warn "
|
|
140
|
+
%s#%s filter expects options to be provided as a Hash or Array or via a block.
|
|
141
|
+
If block given, it should return a Hash or Array
|
|
142
|
+
" % [self.class, setup[:label]]
|
|
143
|
+
{}
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module InstanceMixin
|
|
3
|
+
|
|
4
|
+
attr_reader :items
|
|
5
|
+
attr_accessor :item, :item_id, :column
|
|
6
|
+
|
|
7
|
+
def orm
|
|
8
|
+
@__rear__orm ||= RearORM.new(__rear__.model, __rear__.pkey)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def dom_id
|
|
12
|
+
@__rear__dom_id ||= (params[:dom_id] || # params[:dom_id] are used by decorative filters
|
|
13
|
+
(@reverse_assoc ? @reverse_assoc.dom_id : 'rear_element_%s' % self.__id__)).freeze
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def model
|
|
17
|
+
__rear__.model
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def sequel?
|
|
21
|
+
@@__rear__is_sequel ||= RearUtils.orm(model) == :sq
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def pkey
|
|
25
|
+
__rear__.pkey
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def assocs *types
|
|
29
|
+
return __rear__.assocs if types.empty?
|
|
30
|
+
types.inject({}) do |assocs,type|
|
|
31
|
+
assocs.merge(__rear__.assocs[type.to_sym] || {})
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def template_cache template
|
|
36
|
+
((@__rear__template_cache ||= {})[template] ||= {})[File.mtime(template)] ||= File.read(template)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# used for cosmetic compatibility between filters and columns.
|
|
40
|
+
# columns block are executed inside Column instance,
|
|
41
|
+
# and using `options` method to define options for :select/:radio/:checkbox columns.
|
|
42
|
+
# filters of these types also uses a block and it is executed in controller's context.
|
|
43
|
+
# so adding this method here will allow to use `options` method inside filter's block.
|
|
44
|
+
#
|
|
45
|
+
# @example
|
|
46
|
+
# filter :colors do
|
|
47
|
+
# options 'Red', 'Green', 'Blue'
|
|
48
|
+
# end
|
|
49
|
+
# # this is equivalent to
|
|
50
|
+
# filter :colors do
|
|
51
|
+
# ['Red', 'Green', 'Blue']
|
|
52
|
+
# end
|
|
53
|
+
# # but looks cosmetically better cause uses same syntax as columns
|
|
54
|
+
#
|
|
55
|
+
def options *args
|
|
56
|
+
args
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def associated_model_controller model
|
|
60
|
+
(@__rear__associated_model_controllers ||= {})[model] ||=
|
|
61
|
+
RearUtils.associated_model_controller(model, :ensure_mounted)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def __rear__
|
|
65
|
+
self.class
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def readonly?
|
|
69
|
+
self.class.readonly?
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module InstanceMixin
|
|
3
|
+
|
|
4
|
+
# flip-flopping vectors, that's it, if current vector set to asc
|
|
5
|
+
# this method will return desc, and vice-versa.
|
|
6
|
+
# also it will return UI arrow direction - when vector is asc
|
|
7
|
+
# arrow is down and arrow is up when vector is desc
|
|
8
|
+
def sortable_vector column
|
|
9
|
+
vector = ['asc', nil].include?(order_params[column.string_name]) ? 'desc' : 'asc'
|
|
10
|
+
[vector, vector == 'asc' ? 'down' : 'up']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# checks whether ordering is happening by given column
|
|
14
|
+
# and if it is, check whether a valid vector used
|
|
15
|
+
def sortable_vector? column
|
|
16
|
+
if vector = (params[:order] || {})[column.string_name]
|
|
17
|
+
valid_sortable_vector? vector
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def valid_sortable_vector? vector
|
|
22
|
+
vector if vector == 'asc' || vector == 'desc'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def order_params
|
|
26
|
+
@__rear__order_params ||= pane_columns.inject({}) do |map,column|
|
|
27
|
+
(vector = sortable_vector?(column)) ?
|
|
28
|
+
map.update(column.string_name => vector) : map
|
|
29
|
+
end.freeze
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def order_params_to_sql
|
|
33
|
+
order = []
|
|
34
|
+
order_params.each_pair do |column_name, vector|
|
|
35
|
+
next unless column = columns.find {|c| c.string_name == column_name}
|
|
36
|
+
case __rear__.orm
|
|
37
|
+
when :dm
|
|
38
|
+
column.order_by.each {|c| order << c.send(vector)}
|
|
39
|
+
when :ar
|
|
40
|
+
columns = column.order_by.map {|c| RearUtils.quote_ar_column(model, c)}
|
|
41
|
+
order << [columns.join(', '), vector].join(' ')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
order.any? ? order : nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module InstanceMixin
|
|
3
|
+
|
|
4
|
+
def pager_linker page, label = nil
|
|
5
|
+
label ||= page
|
|
6
|
+
url = route(action, *action_params__array, pager_params(page))
|
|
7
|
+
return link_to(url, label) unless xhr?
|
|
8
|
+
|
|
9
|
+
onclick = "Rear.switch_page('#%s', '%s');" % [dom_id, url]
|
|
10
|
+
link_to nil, label, onclick: onclick
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pager_params page = nil, filters = nil
|
|
14
|
+
page.is_a?(Hash) && (filters = page) && (page = nil)
|
|
15
|
+
page ||= params[:page]
|
|
16
|
+
{
|
|
17
|
+
page: page.to_s,
|
|
18
|
+
filters: filters || pager_filters,
|
|
19
|
+
quick_filters: opted_quick_filters,
|
|
20
|
+
order: order_params
|
|
21
|
+
}.reject {|k,v| v.nil? || v.empty?}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def pager_filters
|
|
25
|
+
@__rear__pager_filters ||= filters.inject({}) do |map,(column, setups)|
|
|
26
|
+
setups.each do |comparison_function, setup|
|
|
27
|
+
(value = filter?(column, comparison_function)) &&
|
|
28
|
+
(map[column] ||= {})[comparison_function] = value
|
|
29
|
+
end
|
|
30
|
+
map
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module RearHelpers
|
|
2
|
+
module InstanceMixin
|
|
3
|
+
|
|
4
|
+
def reander *args, &proc
|
|
5
|
+
reander_layout(:layout) { render_slim args, &proc }
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def reander_partial path, *rest
|
|
9
|
+
render_slim_p path_to_rear_templates('%s.slim' % path), *rest
|
|
10
|
+
end
|
|
11
|
+
alias reander_p reander_partial
|
|
12
|
+
|
|
13
|
+
def reander_layout path, *rest, &proc
|
|
14
|
+
render_slim_l path_to_rear_templates('%s.slim' % path), *rest, &proc
|
|
15
|
+
end
|
|
16
|
+
alias reander_l reander_layout
|
|
17
|
+
|
|
18
|
+
def path_to_rear_templates *chunks
|
|
19
|
+
template = File.join *chunks.map(&:to_s)
|
|
20
|
+
locations = []
|
|
21
|
+
{
|
|
22
|
+
@__rear__templates_path => File.join(app.root, @__rear__templates_path.to_s),
|
|
23
|
+
@__rear__templates_fullpath => @__rear__templates_fullpath,
|
|
24
|
+
}.select {|k,v| k}.each_value do |prefix|
|
|
25
|
+
locations << File.join(prefix, EUtils.class_to_route(self.class.model)) if self.class.respond_to?(:model)
|
|
26
|
+
locations << File.join(prefix, 'shared-templates')
|
|
27
|
+
end
|
|
28
|
+
locations << PATH__TEMPLATES
|
|
29
|
+
locations.each do |p|
|
|
30
|
+
fp = File.join(p, template)
|
|
31
|
+
return explicit_view_path(fp) if File.file?(fp)
|
|
32
|
+
end
|
|
33
|
+
raise ArgumentError, '%s template not found in any of %s paths' % [template,locations*', ']
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|