lolita 3.1.17 → 3.1.18
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/app/controllers/lolita/field_data_controller.rb +36 -0
- data/app/controllers/lolita/info_controller.rb +12 -1
- data/app/controllers/lolita/rest_controller.rb +8 -3
- data/app/helpers/lolita_helper.rb +12 -1
- data/app/views/components/lolita/configuration/column/_display.html.erb +1 -1
- data/app/views/components/lolita/configuration/column/_header.html.erb +1 -1
- data/app/views/components/lolita/configuration/column/_sort.html.erb +7 -4
- data/app/views/components/lolita/configuration/field/array/_display.html.erb +1 -1
- data/app/views/components/lolita/configuration/field/array/autocomplete/_display.html.haml +11 -0
- data/app/views/components/lolita/configuration/field/array/checkbox/_display.html.haml +8 -0
- data/app/views/components/lolita/configuration/field/array/polymorphic/_display.html.haml +6 -0
- data/app/views/components/lolita/configuration/field/array/polymorphic/_options_for_select.html.haml +1 -0
- data/app/views/components/lolita/configuration/field/array/select/_display.html.erb +1 -1
- data/app/views/components/lolita/configuration/field/string/_display.html.erb +1 -5
- data/app/views/components/lolita/configuration/field/string/disabled/_display.html.erb +1 -1
- data/app/views/components/lolita/configuration/field/string/text/_display.html.erb +1 -1
- data/app/views/components/lolita/configuration/list/_paginator.html.erb +1 -1
- data/app/views/components/lolita/configuration/list/_title.html.erb +6 -1
- data/app/views/components/lolita/configuration/nested_form/_display.html.erb +8 -6
- data/app/views/components/lolita/configuration/search/_display.html.haml +2 -0
- data/app/views/components/lolita/navigation/_tree.html.erb +18 -25
- data/app/views/components/lolita/shared/_header.html.erb +1 -1
- data/app/views/components/lolita/shared/_right_sidebar.html.erb +1 -6
- data/app/views/components/lolita/shared/_save_button.html.erb +6 -0
- data/config/locales/en.yml +9 -1
- data/config/locales/lv.yml +6 -5
- data/config/routes.rb +3 -1
- data/lib/lolita.rb +52 -35
- data/lib/lolita/adapter/abstract_adapter.rb +5 -5
- data/lib/lolita/adapter/active_record.rb +190 -84
- data/lib/lolita/adapter/field_helper.rb +19 -0
- data/lib/lolita/adapter/mongoid.rb +217 -64
- data/lib/lolita/builder.rb +1 -1
- data/lib/lolita/configuration/base.rb +17 -4
- data/lib/lolita/configuration/column.rb +47 -28
- data/lib/lolita/configuration/columns.rb +1 -1
- data/lib/lolita/configuration/factory/field.rb +45 -0
- data/lib/lolita/configuration/factory/tab.rb +18 -0
- data/lib/lolita/configuration/field.rb +30 -115
- data/lib/lolita/configuration/field/array.rb +126 -41
- data/lib/lolita/configuration/field/big_decimal.rb +2 -2
- data/lib/lolita/configuration/field/boolean.rb +2 -2
- data/lib/lolita/configuration/field/date.rb +2 -2
- data/lib/lolita/configuration/field/date_time.rb +2 -2
- data/lib/lolita/configuration/field/float.rb +9 -0
- data/lib/lolita/configuration/field/hash.rb +9 -0
- data/lib/lolita/configuration/field/hidden.rb +2 -2
- data/lib/lolita/configuration/field/integer.rb +2 -3
- data/lib/lolita/configuration/field/range.rb +9 -0
- data/lib/lolita/configuration/field/string.rb +5 -2
- data/lib/lolita/configuration/field/symbol.rb +9 -0
- data/lib/lolita/configuration/field/time.rb +2 -2
- data/lib/lolita/configuration/list.rb +41 -8
- data/lib/lolita/configuration/nested_form.rb +2 -2
- data/lib/lolita/configuration/search.rb +91 -0
- data/lib/lolita/configuration/tab.rb +11 -14
- data/lib/lolita/configuration/tab/content.rb +1 -2
- data/lib/lolita/configuration/tab/default.rb +0 -1
- data/lib/lolita/configuration/tabs.rb +17 -11
- data/lib/lolita/controller_additions.rb +15 -0
- data/lib/lolita/controllers/authorization_helpers.rb +56 -0
- data/lib/lolita/controllers/component_helpers.rb +1 -1
- data/lib/lolita/controllers/internal_helpers.rb +18 -4
- data/lib/lolita/controllers/url_helpers.rb +5 -1
- data/lib/lolita/controllers/user_helpers.rb +23 -11
- data/lib/lolita/dbi/base.rb +7 -1
- data/lib/lolita/hooks.rb +163 -120
- data/lib/lolita/lazy_loader.rb +3 -0
- data/lib/lolita/mapping.rb +25 -2
- data/lib/lolita/modules/rest.rb +1 -1
- data/lib/lolita/navigation/branch.rb +52 -1
- data/lib/lolita/navigation/tree.rb +10 -0
- data/lib/lolita/rails.rb +1 -2
- data/lib/lolita/rails/routes.rb +4 -5
- data/lib/lolita/search/simple.rb +76 -0
- data/lib/lolita/system_configuration/application.rb +7 -1
- data/lolita.gemspec +33 -13
- data/public/stylesheets/lolita/style.css +21 -0
- data/spec/configuration/column_spec.rb +2 -2
- data/spec/configuration/columns_spec.rb +1 -1
- data/spec/configuration/field_spec.rb +14 -43
- data/spec/configuration/list_spec.rb +24 -20
- data/spec/configuration/search_spec.rb +44 -0
- data/spec/configuration/tab_spec.rb +21 -31
- data/spec/configuration/tabs_spec.rb +2 -2
- data/spec/dbi/base_spec.rb +3 -9
- data/spec/rails_app/app/mongoid/post.rb +4 -0
- data/spec/rails_app/config/application.rb +12 -1
- data/spec/rails_app/config/environments/development.rb +6 -2
- data/spec/rails_app/config/environments/production.rb +5 -1
- data/spec/rails_app/config/environments/test.rb +5 -1
- data/spec/search/simple_spec.rb +48 -0
- data/spec/spec_helper.rb +29 -18
- metadata +55 -38
- data/spec/configuration/page_spec.rb +0 -20
data/lib/lolita/builder.rb
CHANGED
@@ -15,9 +15,11 @@ module Lolita
|
|
15
15
|
|
16
16
|
attr_reader :dbi,:klass
|
17
17
|
@@generators=[:tabs,:list]
|
18
|
+
|
18
19
|
class << self
|
20
|
+
|
19
21
|
def add_generator(method)
|
20
|
-
@@generators<<method.to_sym
|
22
|
+
@@generators<<method.to_sym
|
21
23
|
end
|
22
24
|
end
|
23
25
|
# When configuration is defined in class than you don't need to worry about
|
@@ -38,8 +40,9 @@ module Lolita
|
|
38
40
|
# Person.lolita=Lolita::Configuration::Base.new(Person)
|
39
41
|
# Person.lolita.klass #=> Person
|
40
42
|
def initialize(orm_class,&block)
|
43
|
+
@in_callback_mode = false
|
41
44
|
@klass=orm_class
|
42
|
-
@dbi=Lolita::DBI::Base.
|
45
|
+
@dbi=Lolita::DBI::Base.create(orm_class)
|
43
46
|
block_given? ? self.instance_eval(&block) : self.generate!
|
44
47
|
end
|
45
48
|
|
@@ -50,6 +53,10 @@ module Lolita
|
|
50
53
|
Lolita::LazyLoader.lazy_load(self,:@list,Lolita::Configuration::List,@dbi,&block)
|
51
54
|
end
|
52
55
|
|
56
|
+
def list=(new_list)
|
57
|
+
@list = new_list if new_list.is_a?(Lolita::Configuration::List)
|
58
|
+
end
|
59
|
+
|
53
60
|
# Create collection of Lolita::Configuration::Tab, loading lazy.
|
54
61
|
# See Lolita::Configuration::Tabs for details.
|
55
62
|
def tabs &block
|
@@ -60,7 +67,7 @@ module Lolita
|
|
60
67
|
# Tabs should not be defined in lolita block to create onew or more Lolita::Configuration::Tab
|
61
68
|
# See Lolita::Configuration::Tab for details of defination.
|
62
69
|
def tab *args, &block
|
63
|
-
self.tabs<<Lolita::Configuration::Tab.add(@dbi,*args,&block)
|
70
|
+
self.tabs<<Lolita::Configuration::Factory::Tab.add(@dbi,*args,&block)
|
64
71
|
end
|
65
72
|
|
66
73
|
# Call all supported instance metods to set needed variables and initialize object with them.
|
@@ -69,7 +76,13 @@ module Lolita
|
|
69
76
|
self.send(generator)
|
70
77
|
}
|
71
78
|
end
|
72
|
-
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def after_initialize
|
83
|
+
@dbi.klass.run(:after_lolita_loaded, :once => self)
|
84
|
+
end
|
85
|
+
|
73
86
|
end
|
74
87
|
end
|
75
88
|
end
|
@@ -12,7 +12,21 @@ module Lolita
|
|
12
12
|
self.set_attributes(*args)
|
13
13
|
self.instance_eval(&block) if block_given?
|
14
14
|
validate
|
15
|
-
|
15
|
+
end
|
16
|
+
|
17
|
+
def value(record)
|
18
|
+
if self.name.to_s.match(/_id$/) && record.respond_to?(self.name.to_s.gsub(/_id$/,"").to_sym)
|
19
|
+
remote_record = record.send(self.name.to_s.gsub(/_id$/,"").to_sym)
|
20
|
+
if remote_record.respond_to?(:title)
|
21
|
+
remote_record.send(:title)
|
22
|
+
elsif remote_record.respond_to?(:name)
|
23
|
+
remote_record.send(:name)
|
24
|
+
else
|
25
|
+
record.send(self.name)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
record.send(self.name)
|
29
|
+
end
|
16
30
|
end
|
17
31
|
|
18
32
|
def title(value=nil)
|
@@ -24,20 +38,34 @@ module Lolita
|
|
24
38
|
def sortable?
|
25
39
|
@sortable
|
26
40
|
end
|
27
|
-
|
28
|
-
def
|
29
|
-
@sortable && params[
|
41
|
+
|
42
|
+
def current_sort_state(params)
|
43
|
+
@sortable && sort_pairs(params).detect{|pair| pair[0]==self.name.to_s} || []
|
30
44
|
end
|
31
45
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
46
|
+
def sort_params params
|
47
|
+
if @sortable
|
48
|
+
pairs = sort_pairs(params)
|
49
|
+
found_pair = false
|
50
|
+
pairs.each_with_index{|pair,index|
|
51
|
+
if pair[0] == self.name.to_s
|
52
|
+
pairs[index][1] = pair[1] == "asc" ? "desc" : "asc"
|
53
|
+
found_pair = true
|
54
|
+
end
|
55
|
+
}
|
56
|
+
unless found_pair
|
57
|
+
pairs << [self.name.to_s,"asc"]
|
58
|
+
end
|
59
|
+
(pairs.map{|pair| pair.join(",")}).join("|")
|
35
60
|
else
|
36
|
-
"
|
61
|
+
""
|
37
62
|
end
|
38
|
-
{:sc=>self.name,:sd=>direction}
|
39
63
|
end
|
40
|
-
|
64
|
+
|
65
|
+
def sort_pairs params
|
66
|
+
(params[:s] || "").split("|").map{|pair| pair.split(",")}
|
67
|
+
end
|
68
|
+
|
41
69
|
# Define format, for details see Lolita::Support::Formatter and Lolita::Support::Formater::Rails
|
42
70
|
def formatter(value=nil,&block)
|
43
71
|
if block_given?
|
@@ -61,29 +89,20 @@ module Lolita
|
|
61
89
|
end
|
62
90
|
|
63
91
|
def set_attributes(*args)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
}
|
69
|
-
elsif args[0].is_a?(Symbol) || args[0].is_a?(String)
|
70
|
-
self.name=args[0].to_s
|
71
|
-
if args[1].is_a?(Hash)
|
72
|
-
args[1].each{|m,value|
|
73
|
-
self.send("#{m}=".to_sym,value)
|
74
|
-
}
|
75
|
-
end
|
76
|
-
else
|
77
|
-
raise ArgumentError.new("Lolita::Configuration::Column arguments must be Hash or Symbol or String instead of #{args[0].class}")
|
92
|
+
options = args ? args.extract_options! : {}
|
93
|
+
if args[0].respond_to?(:field)
|
94
|
+
[:name,:type].each do |attr|
|
95
|
+
self.send(:"#{attr}=",args[0].send(attr))
|
78
96
|
end
|
97
|
+
elsif args[0]
|
98
|
+
self.name = args[0]
|
99
|
+
end
|
100
|
+
options.each do |attr_name,value|
|
101
|
+
self.send(:"#{attr_name}=",value)
|
79
102
|
end
|
80
103
|
end
|
81
104
|
|
82
105
|
private
|
83
|
-
|
84
|
-
def set_default_values
|
85
|
-
@sort_direction||=:desc
|
86
|
-
end
|
87
106
|
|
88
107
|
def validate
|
89
108
|
raise ArgumentError.new("Column must have name.") unless self.name
|
@@ -28,7 +28,7 @@ module Lolita
|
|
28
28
|
def generate!
|
29
29
|
@columns.clear
|
30
30
|
@dbi.fields.each_with_index{|field,index|
|
31
|
-
unless
|
31
|
+
unless field.technical?
|
32
32
|
@columns << Lolita::Configuration::Column.new(@dbi,field)
|
33
33
|
end
|
34
34
|
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Lolita
|
2
|
+
module Configuration
|
3
|
+
module Factory
|
4
|
+
class Field
|
5
|
+
# There are three ways to add field.
|
6
|
+
# *<tt>first</tt> - Pass name and type
|
7
|
+
# Field.add(dbi,"name","type")
|
8
|
+
# *<tt>second</tt> - Pass it through hash
|
9
|
+
# Field.add(dbi,:name => "name", :type => "type")
|
10
|
+
# *<tt>third</tt> - Pass dbi_field
|
11
|
+
# Field.add(dbi,:dbi_field => dbi.fields.first)
|
12
|
+
def self.add(dbi,*args,&block)
|
13
|
+
|
14
|
+
options = args ? args.extract_options! : {}
|
15
|
+
dbi_field = options[:dbi_field]
|
16
|
+
name = args[0] || options[:name] || (dbi_field ? dbi_field.name : nil)
|
17
|
+
dbi_field ||= dbi.field_by_name(name)
|
18
|
+
dbi_field ||= dbi.field_by_association(name)
|
19
|
+
association ||= detect_association(dbi,name)
|
20
|
+
|
21
|
+
type = args[1] || options[:type] ||
|
22
|
+
(association ? :array : nil ) ||
|
23
|
+
(dbi_field ? dbi_field.type : nil) ||
|
24
|
+
:string
|
25
|
+
options[:dbi_field] = dbi_field
|
26
|
+
if !name || !type
|
27
|
+
raise Lolita::FieldTypeError, "type not defined. Set is as second argument or as :dbi_field where value is Adapter::[ORM]::Field object."
|
28
|
+
else
|
29
|
+
|
30
|
+
field_class(type).new(dbi,name,type,options,&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.detect_association(dbi,name)
|
36
|
+
dbi.associations[name.to_sym]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.field_class(name)
|
40
|
+
("Lolita::Configuration::Field::"+name.to_s.camelize).constantize
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Lolita
|
2
|
+
module Configuration
|
3
|
+
module Factory
|
4
|
+
class Tab
|
5
|
+
|
6
|
+
def self.add(dbi,*args, &block)
|
7
|
+
type = args && args[0].is_a?(Symbol) ? args[0] : :default
|
8
|
+
field_class(type).new(dbi,*args,&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.field_class(name)
|
12
|
+
("Lolita::Configuration::Tab::"+name.to_s.camelize).constantize
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -28,47 +28,25 @@ module Lolita
|
|
28
28
|
class Base
|
29
29
|
include Lolita::Builder
|
30
30
|
|
31
|
-
@@default_type=
|
32
|
-
lolita_accessor :name,:title,:field_set, :nested_form,:nested_for,:options, :html_options
|
31
|
+
@@default_type = :string
|
32
|
+
lolita_accessor :name,:title,:field_set, :nested_form,:nested_for,:options, :html_options
|
33
33
|
attr_reader :dbi,:nested_in
|
34
|
+
attr_accessor :dbi_field
|
34
35
|
|
35
|
-
def initialize dbi,
|
36
|
+
def initialize dbi,name,*args, &block
|
36
37
|
@dbi=dbi
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
process_type unless @type
|
43
|
-
end
|
44
|
-
set_default_values
|
45
|
-
validate
|
46
|
-
rescue Exception=>e
|
47
|
-
unless Lolita::Configuration::Field.temp_object?
|
48
|
-
raise e
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def value value=nil, &block
|
54
|
-
self.send(:value=,value,&block) if value || block_given?
|
55
|
-
unless @value
|
56
|
-
self.record_value
|
57
|
-
else
|
58
|
-
if @value.is_a?(Proc)
|
59
|
-
@value.call(self)
|
60
|
-
else
|
61
|
-
@value
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
38
|
+
self.name = name
|
39
|
+
options = args ? args.extract_options! : {}
|
40
|
+
type = args[0]
|
41
|
+
|
42
|
+
self.type = type || @@default_type
|
65
43
|
|
66
|
-
|
44
|
+
self.set_attributes(options)
|
67
45
|
if block_given?
|
68
|
-
|
69
|
-
else
|
70
|
-
@value=value
|
46
|
+
self.instance_eval(&block)
|
71
47
|
end
|
48
|
+
set_default_values
|
49
|
+
validate
|
72
50
|
end
|
73
51
|
|
74
52
|
def title(value=nil)
|
@@ -87,18 +65,16 @@ module Lolita
|
|
87
65
|
end
|
88
66
|
|
89
67
|
def name=(value)
|
90
|
-
@name=value ? value.to_sym : nil
|
91
|
-
end
|
92
|
-
|
93
|
-
def type_name
|
94
|
-
self.type.to_s.downcase
|
68
|
+
@name= value ? value.to_sym : nil
|
95
69
|
end
|
96
70
|
|
97
71
|
def nested_in=(dbi)
|
98
72
|
unless self.dbi.associations_class_names.include?(dbi.klass.to_s)
|
99
73
|
raise Lolita::ReferenceError, "There is no association between #{self.dbi.klass} and #{dbi.klass}"
|
100
74
|
end
|
101
|
-
|
75
|
+
if !dbi.is_a?(Lolita::DBI::Base) && !dbi.class.to_s.match(/Lolita::Adapter/)
|
76
|
+
raise ArgumentError, "Field can be nested only in Lolita::DBI::Base object."
|
77
|
+
end
|
102
78
|
@nested_in=dbi
|
103
79
|
end
|
104
80
|
|
@@ -107,29 +83,26 @@ module Lolita
|
|
107
83
|
end
|
108
84
|
|
109
85
|
def nested_in?(dbi_or_class)
|
110
|
-
if dbi_or_class.
|
86
|
+
if dbi_or_class.respond_to?(:klass)
|
111
87
|
self.nested_in && self.nested_in.klass==dbi_or_class.klass
|
112
88
|
else
|
113
89
|
self.nested_in && self.nested_in.klass==dbi_or_class
|
114
90
|
end
|
115
91
|
end
|
116
92
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
93
|
+
def set_attributes(attributes)
|
94
|
+
excluded_keys = [:name,:type]
|
95
|
+
attributes.each{|attr,value|
|
96
|
+
unless excluded_keys.include?(attr.to_sym)
|
121
97
|
self.send(:"#{attr}=",value)
|
122
98
|
end
|
123
99
|
}
|
124
100
|
end
|
125
101
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
else
|
131
|
-
nil
|
132
|
-
end
|
102
|
+
def find_dbi_field
|
103
|
+
@dbi_field ||= self.dbi.fields.detect{|field|
|
104
|
+
field.name.to_s == @name.to_s || (field.association && field.association.name.to_s == @name.to_s)
|
105
|
+
}
|
133
106
|
end
|
134
107
|
|
135
108
|
private
|
@@ -141,77 +114,19 @@ module Lolita
|
|
141
114
|
def set_default_values
|
142
115
|
self.options||={}
|
143
116
|
self.html_options ||= {}
|
144
|
-
|
145
|
-
|
146
|
-
def before_init *args
|
147
|
-
extract_args *args
|
148
|
-
set_name
|
149
|
-
if @name
|
150
|
-
process_type
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def process_type
|
155
|
-
set_association
|
156
|
-
set_type_from_args
|
157
|
-
set_type
|
158
|
-
end
|
159
|
-
|
160
|
-
def extract_args *args
|
161
|
-
if args
|
162
|
-
@given_args=args
|
163
|
-
@given_attributes=@given_args.extract_options!
|
117
|
+
@html_options[:class] = if @html_options[:class]
|
118
|
+
"#{@html_options[:class]} #{self.type}"
|
164
119
|
else
|
165
|
-
|
166
|
-
@given_attributes={}
|
120
|
+
self.type.to_s
|
167
121
|
end
|
168
122
|
end
|
169
123
|
|
170
|
-
def set_name
|
171
|
-
if @given_args.first
|
172
|
-
self.name=@given_args.first
|
173
|
-
else
|
174
|
-
self.name=@given_attributes[:name]
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def set_type_from_args
|
179
|
-
self.type=@given_args[1] if @given_args[1]
|
180
|
-
end
|
181
|
-
|
182
|
-
def set_type
|
183
|
-
if !@type
|
184
|
-
if @association
|
185
|
-
self.type="array"
|
186
|
-
elsif dbi_field=self.dbi.fields.detect{|f| f[:name].to_s==@name.to_s}
|
187
|
-
self.type=dbi_field[:type]
|
188
|
-
self.options=dbi_field[:options]
|
189
|
-
end
|
190
|
-
end
|
191
|
-
if @type.nil? || @type.to_s.downcase=="object"
|
192
|
-
self.type=@@default_type
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
# Need here because this don't know how to recognize association.
|
197
|
-
# TODO maybe need move to adapter, and it is converted there
|
198
|
-
def set_association #TODO test
|
199
|
-
assoc_name=@name.to_s.gsub(/_id$/,"")
|
200
|
-
@association||=@dbi.reflect_on_association(assoc_name.to_sym) ||
|
201
|
-
@dbi.reflect_on_association(assoc_name.pluralize.to_sym)
|
202
|
-
end
|
203
|
-
|
204
124
|
def validate
|
205
125
|
unless self.name
|
206
126
|
raise Lolita::FieldNameError, "Field must have name."
|
207
127
|
end
|
208
|
-
#FIXME need this validation
|
209
|
-
# if !@value && !@dbi.klass.instance_methods.include?(self.name.to_s)
|
210
|
-
# raise Lolita::FieldNameError, "#{@dbi.klass} must respond to #{self.name} method."
|
211
|
-
# end
|
212
128
|
end
|
213
|
-
|
214
129
|
end
|
215
130
|
end
|
216
131
|
end
|
217
|
-
end
|
132
|
+
end
|