lipsiadmin 5.1.6 → 5.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/access_control/authentication.rb +20 -20
- data/lib/access_control/base.rb +40 -40
- data/lib/controller/ext.rb +27 -27
- data/lib/controller/lipsiadmin_controller.rb +3 -3
- data/lib/controller/pdf_builder.rb +33 -31
- data/lib/controller/rescue.rb +12 -12
- data/lib/controller/responds_to_parent.rb +5 -5
- data/lib/data_base/attachment.rb +60 -60
- data/lib/data_base/attachment/attach.rb +18 -18
- data/lib/data_base/attachment/geometry.rb +7 -7
- data/lib/data_base/attachment/iostream.rb +1 -1
- data/lib/data_base/attachment/processor.rb +2 -2
- data/lib/data_base/attachment/storage.rb +11 -11
- data/lib/data_base/attachment/thumbnail.rb +2 -2
- data/lib/data_base/attachment_table.rb +27 -27
- data/lib/data_base/translate_attributes.rb +9 -9
- data/lib/data_base/utility_scopes.rb +7 -7
- data/lib/data_base/without_table.rb +10 -10
- data/lib/generator.rb +4 -4
- data/lib/loops.rb +77 -77
- data/lib/loops/base.rb +2 -2
- data/lib/loops/daemonize.rb +5 -5
- data/lib/loops/process_manager.rb +3 -3
- data/lib/loops/worker.rb +1 -1
- data/lib/loops/worker_pool.rb +1 -1
- data/lib/mailer/exception_notifier.rb +5 -5
- data/lib/mailer/pdf_builder.rb +20 -18
- data/lib/utils/literal.rb +6 -6
- data/lib/utils/pdf_builder.rb +10 -10
- data/lib/version.rb +1 -1
- data/lib/view/helpers/backend_helper.rb +123 -123
- data/lib/view/helpers/ext/button.rb +7 -7
- data/lib/view/helpers/ext/column_model.rb +18 -18
- data/lib/view/helpers/ext/component.rb +50 -50
- data/lib/view/helpers/ext/configuration.rb +5 -5
- data/lib/view/helpers/ext/grid.rb +46 -46
- data/lib/view/helpers/ext/store.rb +14 -14
- data/lib/view/helpers/ext/tool_bar.rb +6 -6
- data/lib/view/helpers/ext_helper.rb +21 -21
- data/lib/view/helpers/frontend_helper.rb +5 -5
- data/lib/view/helpers/pdf_helper.rb +7 -7
- data/lib/view/helpers/view_helper.rb +28 -28
- data/lipsiadmin_generators/attachment/attachment_generator.rb +7 -7
- data/lipsiadmin_generators/attachment/templates/controller.rb +13 -13
- data/lipsiadmin_generators/attachment/templates/migration.rb +1 -1
- data/lipsiadmin_generators/backend/backend_generator.rb +9 -9
- data/lipsiadmin_generators/backend/templates/controllers/backend/accounts_controller.rb +10 -10
- data/lipsiadmin_generators/backend/templates/controllers/backend/sessions_controller.rb +2 -2
- data/lipsiadmin_generators/backend/templates/controllers/javascripts_controller.rb +2 -2
- data/lipsiadmin_generators/backend/templates/migrations/create_accounts.rb +5 -5
- data/lipsiadmin_generators/backend/templates/models/account.rb +16 -16
- data/lipsiadmin_generators/backend/templates/models/account_access.rb +11 -11
- data/lipsiadmin_generators/backend/templates/models/notifier.rb +2 -2
- data/lipsiadmin_generators/backend_page/backend_page_generator.rb +22 -22
- data/lipsiadmin_generators/backend_page/templates/controller.rb +9 -9
- data/lipsiadmin_generators/backend_page/templates/functional_test.rb +10 -10
- data/lipsiadmin_generators/frontend/frontend_generator.rb +5 -5
- data/lipsiadmin_generators/frontend/templates/controllers/frontend/sessions_controller.rb +3 -3
- data/lipsiadmin_generators/loops/loops_generator.rb +2 -2
- data/lipsiadmin_generators/pdf/pdf_generator.rb +7 -7
- data/lipsiadmin_generators/state_session/state_session_generator.rb +9 -9
- data/lipsiadmin_generators/state_session/templates/controller.rb +2 -2
- data/lipsiadmin_generators/state_session/templates/migration.rb +2 -2
- data/resources/rdoc/horo.rb +3 -3
- metadata +4 -4
@@ -1,12 +1,12 @@
|
|
1
1
|
module Lipsiadmin#:nodoc:
|
2
2
|
module Ext#:nodoc:
|
3
3
|
# Generate a new Ext.data.GroupingStore
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Examples:
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# var store = new Ext.data.GroupingStore({
|
8
8
|
# reader: new Ext.data.JsonReader({
|
9
|
-
# id:'id',
|
9
|
+
# id:'id',
|
10
10
|
# totalProperty:'count', root:'results',
|
11
11
|
# fields:[{
|
12
12
|
# name: "accounts.name"
|
@@ -26,7 +26,7 @@ module Lipsiadmin#:nodoc:
|
|
26
26
|
# proxy: new Ext.data.HttpProxy({ url:'/backend/accounts.json' }),
|
27
27
|
# remoteSort: true
|
28
28
|
# });
|
29
|
-
#
|
29
|
+
#
|
30
30
|
# grid.store do |store|
|
31
31
|
# store.url "/backend/accounts.json"
|
32
32
|
# store.add "accounts.name"
|
@@ -44,28 +44,28 @@ module Lipsiadmin#:nodoc:
|
|
44
44
|
baseParams("_method" => "GET") if config[:baseParams].blank?
|
45
45
|
yield self if block_given?
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
# The url for getting the json data
|
49
49
|
def url(value)
|
50
50
|
@url = value
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# This add automatically fields from an array
|
54
54
|
def fields(fields)
|
55
55
|
fields.each { |options| add_field(nil, options) }
|
56
56
|
end
|
57
57
|
|
58
|
-
# Add fields to a Ext.data.JsonReader
|
59
|
-
#
|
58
|
+
# Add fields to a Ext.data.JsonReader
|
59
|
+
#
|
60
60
|
# Examples:
|
61
|
-
#
|
61
|
+
#
|
62
62
|
# {
|
63
63
|
# type: "date",
|
64
64
|
# renderer: Ext.util.Format.dateTimeRenderer(),
|
65
65
|
# name: "accounts.datetime",
|
66
66
|
# dateFormat: "c"
|
67
67
|
# }
|
68
|
-
#
|
68
|
+
#
|
69
69
|
# add "accounts.datetime", :type => :datetime
|
70
70
|
#
|
71
71
|
def add_field(name=nil, options={})#:nodoc:
|
@@ -78,8 +78,8 @@ module Lipsiadmin#:nodoc:
|
|
78
78
|
raise ComponentError, "You must provide a Name for all fields" if options[:name].blank?
|
79
79
|
@fields << Configuration.new(options)
|
80
80
|
end
|
81
|
-
|
82
|
-
# Return the javascript for create a new Ext.data.GroupingStore
|
81
|
+
|
82
|
+
# Return the javascript for create a new Ext.data.GroupingStore
|
83
83
|
def to_s
|
84
84
|
raise ComponentError, "You must provide the correct var the store." if get_var.blank?
|
85
85
|
raise ComponentError, "You must provide the url for get the store data." if @url.blank? && config[:proxy].blank?
|
@@ -88,7 +88,7 @@ module Lipsiadmin#:nodoc:
|
|
88
88
|
config[:reader] = default_reader if config[:reader].blank?
|
89
89
|
super
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
private
|
93
93
|
def default_proxy
|
94
94
|
"new Ext.data.HttpProxy(#{Configuration.new(:url => @url).to_s(2)})".to_l
|
@@ -101,4 +101,4 @@ module Lipsiadmin#:nodoc:
|
|
101
101
|
|
102
102
|
end
|
103
103
|
end
|
104
|
-
end
|
104
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Lipsiadmin
|
2
2
|
module Ext
|
3
3
|
# Generate a new Ext.Toolbar
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Examples:
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# var toolBar = new Ext.Toolbar([{
|
8
8
|
# handler: show,
|
9
9
|
# text: "Add",
|
@@ -26,15 +26,15 @@ module Lipsiadmin
|
|
26
26
|
super("Ext.Toolbar", { :buttons => [] }.merge(options))
|
27
27
|
yield self if block_given?
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
# Add new items to a Ext.Toolbar
|
31
|
-
#
|
31
|
+
#
|
32
32
|
# # Generates: { handler: show, text: "Add", other: "...", icon: "..." }
|
33
33
|
# add_button :text => "Add", :handler => "show".to_l, :icon => "...", :other => "..."
|
34
|
-
#
|
34
|
+
#
|
35
35
|
def add_button(options, &block)
|
36
36
|
config[:buttons] << (options.is_a?(String) ? options : Button.new(options, &block).config)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
|
-
end
|
40
|
+
end
|
@@ -11,24 +11,24 @@ module Lipsiadmin
|
|
11
11
|
module Helpers
|
12
12
|
# Module containing the methods useful for ext/prototype
|
13
13
|
module ExtHelper
|
14
|
-
|
14
|
+
|
15
15
|
def self.included(base)#:nodoc:
|
16
16
|
base.class_eval do
|
17
17
|
alias_method_chain :to_s, :refactoring
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def to_s_with_refactoring #:nodoc:
|
22
22
|
returning javascript = @lines * $/ do
|
23
23
|
source = javascript.dup
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
# Hide all open dialogs
|
28
28
|
def hide_dialogs
|
29
29
|
record "Ext.Msg.getDialog().hide()"
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# Replaces the inner HTML of the Main Panel of +Backend+.
|
33
33
|
#
|
34
34
|
# +options_for_render+ may be either a string of HTML to insert, or a hash
|
@@ -37,13 +37,13 @@ module Lipsiadmin
|
|
37
37
|
# # Replaces the inner HTML of the Main Panel of +Backend+.
|
38
38
|
# # Generates: Backend.app.update("-- Contents of 'person' partial --");
|
39
39
|
# page.update :partial => 'person', :object => @person
|
40
|
-
#
|
40
|
+
#
|
41
41
|
def update(*options_for_render)
|
42
42
|
call "Backend.app.update", render(*options_for_render), true
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# Load html/js and eval it's code
|
46
|
-
#
|
46
|
+
#
|
47
47
|
# # Generates: Backend.app.loadJs('/my/javascript.js');
|
48
48
|
# load(:controller => :my, :action => :javascript, :format => :js)
|
49
49
|
#
|
@@ -51,11 +51,11 @@ module Lipsiadmin
|
|
51
51
|
url = location.is_a?(String) ? location : @context.url_for(location)
|
52
52
|
call "Backend.app.load", url
|
53
53
|
end
|
54
|
-
|
55
|
-
# Show errors (if they are) for the given +objects+ and show a Ext.Message
|
54
|
+
|
55
|
+
# Show errors (if they are) for the given +objects+ and show a Ext.Message
|
56
56
|
# with explanation of the errors or if errors are empty, a congratulation message.
|
57
|
-
#
|
58
|
-
# # Generates:
|
57
|
+
#
|
58
|
+
# # Generates:
|
59
59
|
# # Ext.Msg.show({
|
60
60
|
# # title:Backend.locale.messages.alert.title,
|
61
61
|
# # msg: '<ul>Name can't be blank!</ul>',
|
@@ -80,7 +80,7 @@ module Lipsiadmin
|
|
80
80
|
end
|
81
81
|
|
82
82
|
# Show a Ext.alert popup
|
83
|
-
#
|
83
|
+
#
|
84
84
|
# # Generates: Ext.Msg.alert('Hey!', 'Hello World')
|
85
85
|
# ext_alert('Hey!', 'Hello World')
|
86
86
|
#
|
@@ -89,25 +89,25 @@ module Lipsiadmin
|
|
89
89
|
end
|
90
90
|
|
91
91
|
# Unmask the Backend App
|
92
|
-
#
|
92
|
+
#
|
93
93
|
# # Generates: Backend.app.unmask()
|
94
94
|
# unmask
|
95
95
|
#
|
96
96
|
def unmask
|
97
97
|
call "Backend.app.unmask"
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
# Mask the Backend App
|
101
|
-
#
|
101
|
+
#
|
102
102
|
# # Generates: Backend.app.mask('Hello World')
|
103
103
|
# mask("Hello World")
|
104
104
|
#
|
105
105
|
def mask(title=nil)
|
106
106
|
call "Backend.app.mask", title
|
107
|
-
end
|
108
|
-
|
107
|
+
end
|
108
|
+
|
109
109
|
# Create a javascript function
|
110
|
-
#
|
110
|
+
#
|
111
111
|
# # Generates: function() { window.show(); };
|
112
112
|
# page.fn("window.show();")
|
113
113
|
# or
|
@@ -120,7 +120,7 @@ module Lipsiadmin
|
|
120
120
|
record block_to_function(function || block)
|
121
121
|
end
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
# Generate a full customizable Ext.GridPanel
|
125
125
|
#
|
126
126
|
# Examples:
|
@@ -141,11 +141,11 @@ module Lipsiadmin
|
|
141
141
|
# end
|
142
142
|
# grid.bbar :store => grid.get_store, :pageSize => params[:limit]
|
143
143
|
# end
|
144
|
-
#
|
144
|
+
#
|
145
145
|
def grid(options={}, &block)
|
146
146
|
self << Lipsiadmin::Ext::Grid.new(options, &block)
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
150
150
|
end
|
151
|
-
end
|
151
|
+
end
|
@@ -8,23 +8,23 @@ module Lipsiadmin
|
|
8
8
|
def title(text)
|
9
9
|
content_for(:title) { text + " - #{AppConfig.project}" }
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
# Set the meta description of the page
|
13
13
|
# Usefull for google & c.
|
14
14
|
def description(text)
|
15
15
|
content_for(:description) { text }
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
# Set the meta keywords of the page
|
19
19
|
# Usefull for google & c.
|
20
20
|
def keywords(text)
|
21
21
|
content_for(:keywords) { text }
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# Override the default image tag with a special option
|
25
25
|
# <tt>resize</tt> that crop/resize on the fly the image
|
26
26
|
# and store them in <tt>uploads/thumb</tt> directory.
|
27
|
-
#
|
27
|
+
#
|
28
28
|
def image_tag(source, options = {})
|
29
29
|
options.symbolize_keys!
|
30
30
|
# We set here the upload path
|
@@ -86,4 +86,4 @@ module Lipsiadmin
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
|
-
end
|
89
|
+
end
|
@@ -3,13 +3,13 @@ module Lipsiadmin
|
|
3
3
|
module Helpers
|
4
4
|
# This helper is necessary for when we generate some PDF
|
5
5
|
# remember that basically pdf are standard html pages
|
6
|
-
# and we use PD4ML for convert it in PDF.
|
7
|
-
#
|
6
|
+
# and we use PD4ML for convert it in PDF.
|
7
|
+
#
|
8
8
|
# So for example is necessary have an header for all pdf page
|
9
9
|
# and a footer.
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Here you can find helpers for do that.
|
12
|
-
#
|
12
|
+
#
|
13
13
|
module PdfHelper
|
14
14
|
# Return the pd4ml header tag block
|
15
15
|
def pdf_header(&block)
|
@@ -22,7 +22,7 @@ module Lipsiadmin
|
|
22
22
|
HTML
|
23
23
|
concat(html)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Return the pd4ml footer tag block
|
27
27
|
def pdf_footer(&block)
|
28
28
|
html = <<-HTML
|
@@ -33,7 +33,7 @@ module Lipsiadmin
|
|
33
33
|
HTML
|
34
34
|
block_given? ? concat(html) : html
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
# Return the pd4ml page break tag
|
38
38
|
def pdf_page_break
|
39
39
|
"<pd4ml:page.break>"
|
@@ -42,4 +42,4 @@ module Lipsiadmin
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
@@ -3,9 +3,9 @@ require 'action_view/helpers/tag_helper'
|
|
3
3
|
module Lipsiadmin
|
4
4
|
module View
|
5
5
|
module Helpers#:nodoc:
|
6
|
-
# Returns text_area, text_field, password_field with
|
6
|
+
# Returns text_area, text_field, password_field with
|
7
7
|
# a default extjs css style.
|
8
|
-
#
|
8
|
+
#
|
9
9
|
module FormHelper
|
10
10
|
def self.included(base)#:nodoc:
|
11
11
|
base.alias_method_chain :text_area, :style
|
@@ -15,9 +15,9 @@ module Lipsiadmin
|
|
15
15
|
|
16
16
|
# Returns text_area with extjs style
|
17
17
|
# alias for text_area, for use the original tag use:
|
18
|
-
#
|
18
|
+
#
|
19
19
|
# text_area_without_style
|
20
|
-
#
|
20
|
+
#
|
21
21
|
def text_area_with_style(name, value = nil, options = {})
|
22
22
|
options[:class] ||= "x-form-field"
|
23
23
|
options[:style] ||= "width:100%;height:80px"
|
@@ -26,20 +26,20 @@ module Lipsiadmin
|
|
26
26
|
|
27
27
|
# Returns text_field with extjs style
|
28
28
|
# alias for text_field, for use the original tag use:
|
29
|
-
#
|
29
|
+
#
|
30
30
|
# text_field_without_style
|
31
|
-
#
|
31
|
+
#
|
32
32
|
def text_field_with_style(name, method, options = {})
|
33
33
|
options[:class] ||= "x-form-text"
|
34
34
|
options[:style] ||= "width:100%"
|
35
35
|
text_field_without_style(name, method, options)
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Returns password_field with extjs style
|
39
39
|
# alias for password_field, for use the original tag use:
|
40
|
-
#
|
40
|
+
#
|
41
41
|
# password_field_without_style
|
42
|
-
#
|
42
|
+
#
|
43
43
|
def password_field_with_style(name, method, options = {})
|
44
44
|
options[:class] ||= "x-form-text"
|
45
45
|
options[:style] ||= "width:100%"
|
@@ -47,11 +47,11 @@ module Lipsiadmin
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
# Returns text_area_tag, text_field_tag, password_field_tag with
|
50
|
+
# Returns text_area_tag, text_field_tag, password_field_tag with
|
51
51
|
# a default extjs css style.
|
52
|
-
#
|
52
|
+
#
|
53
53
|
module FormTagHelper
|
54
|
-
|
54
|
+
|
55
55
|
def self.included(base)#:nodoc:
|
56
56
|
base.alias_method_chain :text_field_tag, :style
|
57
57
|
base.alias_method_chain :text_area_tag, :style
|
@@ -60,9 +60,9 @@ module Lipsiadmin
|
|
60
60
|
|
61
61
|
# Returns text_area_tag with extjs style
|
62
62
|
# alias for text_area_tag, for use the original tag use:
|
63
|
-
#
|
63
|
+
#
|
64
64
|
# text_area_tag_without_style
|
65
|
-
#
|
65
|
+
#
|
66
66
|
def text_area_tag_with_style(name, value = nil, options = {})
|
67
67
|
options[:class] ||= "x-form-field"
|
68
68
|
options[:style] ||= "width:100%;height:80px"
|
@@ -71,39 +71,39 @@ module Lipsiadmin
|
|
71
71
|
|
72
72
|
# Returns text_field_tag with extjs style
|
73
73
|
# alias for text_field_tag, for use the original tag use:
|
74
|
-
#
|
74
|
+
#
|
75
75
|
# text_field_tag_without_style
|
76
|
-
#
|
76
|
+
#
|
77
77
|
def text_field_tag_with_style(name, value = nil, options = {})
|
78
78
|
options[:class] ||= "x-form-text"
|
79
79
|
options[:style] ||= "width:100%"
|
80
80
|
text_field_tag_without_style(name, value, options)
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
# Returns password_field_tag with extjs style
|
84
84
|
# alias for password_field_tag, for use the original tag use:
|
85
|
-
#
|
85
|
+
#
|
86
86
|
# password_field_tag_style
|
87
|
-
#
|
87
|
+
#
|
88
88
|
def password_field_tag_with_style(name, value = nil, options = {})
|
89
89
|
options[:class] ||= "x-form-text"
|
90
90
|
options[:style] ||= "width:100%"
|
91
91
|
password_field_tag_without_style(name, value, options)
|
92
92
|
end
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
module DateHelper
|
96
96
|
# Returns an ExtJs Calendar
|
97
|
-
#
|
97
|
+
#
|
98
98
|
# Examples:
|
99
99
|
# =ext_date_select :post, :created_at
|
100
|
-
#
|
100
|
+
#
|
101
101
|
def ext_date_select(object_name, method, options = {}, html_options = {})
|
102
102
|
InstanceTag.new(object_name, method, self, options.delete(:object)).to_ext_date_select_tag(options, html_options)
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
# Returns an ExtJs Calendar and a Time selector
|
106
|
-
#
|
106
|
+
#
|
107
107
|
# Examples:
|
108
108
|
# =ext_datetime_select :post, :updated_at
|
109
109
|
#
|
@@ -174,7 +174,7 @@ module Lipsiadmin
|
|
174
174
|
|
175
175
|
class InstanceTag < ActionView::Helpers::InstanceTag#:nodoc:
|
176
176
|
include CountrySelectHelper
|
177
|
-
|
177
|
+
|
178
178
|
def to_ext_date_select_tag(options = {}, html_options = {})
|
179
179
|
to_ext_datetime_select_tag({ :hideTime => true.to_l }.merge(options), html_options)
|
180
180
|
end
|
@@ -190,7 +190,7 @@ module Lipsiadmin
|
|
190
190
|
tag("input", html_options) +
|
191
191
|
content_tag(:script, "new Ext.form.DateTimeField(#{options.to_json});", :type => Mime::JS)
|
192
192
|
end
|
193
|
-
|
193
|
+
|
194
194
|
def to_country_select_tag(priority_countries, options, html_options)
|
195
195
|
html_options = html_options.stringify_keys
|
196
196
|
add_default_name_and_id(html_options)
|
@@ -212,11 +212,11 @@ module Lipsiadmin
|
|
212
212
|
def ext_datetime_select(method, options = {}, html_options = {})
|
213
213
|
@template.ext_datetime_select(@object_name, method, options.merge(:object => @object), html_options)
|
214
214
|
end
|
215
|
-
|
215
|
+
|
216
216
|
def country_select(method, priority_countries = nil, options = {}, html_options = {})
|
217
217
|
@template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options)
|
218
218
|
end
|
219
219
|
end
|
220
220
|
end
|
221
221
|
end
|
222
|
-
end
|
222
|
+
end
|