active_scaffold 3.2.15 → 3.2.16
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +11 -1
- data/app/assets/javascripts/jquery/active_scaffold.js +7 -0
- data/app/assets/javascripts/prototype/active_scaffold.js +10 -0
- data/frontends/default/views/_form.html.erb +4 -3
- data/frontends/default/views/_list_inline_adapter.html.erb +2 -1
- data/frontends/default/views/on_create.js.erb +3 -1
- data/lib/active_scaffold/actions/core.rb +5 -4
- data/lib/active_scaffold/actions/list.rb +4 -0
- data/lib/active_scaffold/actions/mark.rb +2 -3
- data/lib/active_scaffold/attribute_params.rb +1 -1
- data/lib/active_scaffold/data_structures/nested_info.rb +2 -2
- data/lib/active_scaffold/finder.rb +2 -0
- data/lib/active_scaffold/helpers/controller_helpers.rb +2 -6
- data/lib/active_scaffold/helpers/form_column_helpers.rb +8 -0
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/list_column_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/view_helpers.rb +11 -4
- data/lib/active_scaffold/version.rb +1 -1
- metadata +9 -10
- data/lib/active_scaffold/extensions/active_association_reflection.rb +0 -22
data/CHANGELOG
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
= 3.2.
|
1
|
+
= 3.2.16
|
2
|
+
- Fix use of column.css_class in form when is a proc, it wasn't skipped when form was a columns group
|
3
|
+
- Fix constraints and colspan in self-referential associations
|
4
|
+
- Fix rendering parent row after creating or updating in a nested form (singular associations)
|
5
|
+
- Translate include_blank and prompt in form_ui :select
|
6
|
+
- Fix mark for nested scaffolds
|
7
|
+
- Fix STI creation
|
8
|
+
- Fix null search for numeric columns
|
9
|
+
- Fix recordselect inplace_edit with plural associations in ruby 1.9
|
10
|
+
|
11
|
+
= 3.2.15
|
2
12
|
- Prepare to unify field overrides and list_ui method signatures
|
3
13
|
- Add :optional to update.persistent
|
4
14
|
- Add missing triggering of as:element_updated in new subform rows
|
@@ -504,6 +504,13 @@ var ActiveScaffold = {
|
|
504
504
|
this.increment_record_count(tbody.closest('div.active-scaffold'));
|
505
505
|
ActiveScaffold.highlight(new_row);
|
506
506
|
},
|
507
|
+
|
508
|
+
create_record_row_from_url: function(active_scaffold_id, url, options) {
|
509
|
+
jQuery.get(url, function(row) {
|
510
|
+
ActiveScaffold.create_record_row(action_link.scaffold(), row, options);
|
511
|
+
action_link.close();
|
512
|
+
});
|
513
|
+
},
|
507
514
|
|
508
515
|
delete_record_row: function(row, page_reload_url) {
|
509
516
|
if (typeof(row) == 'string') row = '#' + row;
|
@@ -454,6 +454,16 @@ var ActiveScaffold = {
|
|
454
454
|
this.increment_record_count(tbody.up('div.active-scaffold'));
|
455
455
|
ActiveScaffold.highlight(new_row);
|
456
456
|
},
|
457
|
+
|
458
|
+
create_record_row_from_url: function(action_link, url, options) {
|
459
|
+
new Ajax.Request(url, {
|
460
|
+
method: 'get',
|
461
|
+
onComplete: function(response) {
|
462
|
+
ActiveScaffold.create_record_row(action_link.scaffold(), row, options);
|
463
|
+
action_link.close();
|
464
|
+
}
|
465
|
+
});
|
466
|
+
},
|
457
467
|
|
458
468
|
delete_record_row: function(row, page_reload_url) {
|
459
469
|
row = $(row);
|
@@ -5,21 +5,22 @@
|
|
5
5
|
%>
|
6
6
|
<ol class="form" <%= "id=#{subsection_id}" unless subsection_id.nil? %> <%= "style=\"display: none;\"".html_safe if columns.collapsed %>>
|
7
7
|
<% columns.each :for => @record, :crud_type => (:read if show_unauthorized_columns) do |column| %>
|
8
|
+
<% column_css_class = column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc) %>
|
8
9
|
<% authorized = show_unauthorized_columns ? @record.authorized_for?(:crud_type => form_action, :column => column.name) : true %>
|
9
10
|
<% renders_as = column_renders_as(column) %>
|
10
11
|
<% if renders_as == :subsection -%>
|
11
12
|
<% subsection_id = sub_section_id(:sub_section => column.label) %>
|
12
|
-
<li class="sub-section <%=
|
13
|
+
<li class="sub-section <%= column_css_class %>">
|
13
14
|
<h5><%= column.label %></h5>
|
14
15
|
<%= render :partial => 'form', :locals => { :columns => column, :subsection_id => subsection_id, :form_action => form_action, :scope => scope } %>
|
15
16
|
<%= link_to_visibility_toggle(subsection_id, {:default_visible => !column.collapsed}) -%>
|
16
17
|
</li>
|
17
18
|
<% elsif renders_as == :subform and !override_form_field?(column) and authorized -%>
|
18
|
-
<li class="sub-form <%= active_scaffold_config_for(column.association.klass).subform.layout %>-sub-form <%=
|
19
|
+
<li class="sub-form <%= active_scaffold_config_for(column.association.klass).subform.layout %>-sub-form <%= column_css_class %> <%=column.name%>-sub-form" id="<%= sub_form_id(:association => column.name) %>">
|
19
20
|
<%=raw render :partial => form_partial_for_column(column, renders_as), :locals => { :column => column, :scope => scope } -%>
|
20
21
|
</li>
|
21
22
|
<% else -%>
|
22
|
-
<li class="form-element <%= 'required' if column.required? %> <%=
|
23
|
+
<li class="form-element <%= 'required' if column.required? %> <%= column_css_class %>">
|
23
24
|
<%=raw render :partial => form_partial_for_column(column, renders_as), :locals => { :column => column, :only_value => !authorized, :scope => scope } -%>
|
24
25
|
</li>
|
25
26
|
<% end -%>
|
@@ -5,7 +5,8 @@
|
|
5
5
|
else
|
6
6
|
active_scaffold_config
|
7
7
|
end
|
8
|
-
config
|
8
|
+
# increment in 1 for self-associations, parent_model config will have constraints too
|
9
|
+
config.list.columns.count + 1 + (config == active_scaffold_config ? 1 : 0)
|
9
10
|
end
|
10
11
|
%>
|
11
12
|
<%# nested_id, allows us to remove a nested scaffold programmatically %>
|
@@ -5,8 +5,10 @@ var action_link = ActiveScaffold.find_action_link('<%= form_selector%>');
|
|
5
5
|
action_link.update_flash_messages('<%=escape_javascript(render(:partial => 'messages'))%>');
|
6
6
|
<% if controller.send :successful? %>
|
7
7
|
<% if render_parent? %>
|
8
|
-
<% if nested_singular_association?
|
8
|
+
<% if nested_singular_association? %>
|
9
9
|
action_link.close(true);
|
10
|
+
<% elsif params[:parent_sti] && render_parent_action == :row %>
|
11
|
+
ActiveScaffold.create_record_row_from_url(action_link,'<%= url_for(render_parent_options) %>', <%= {:insert_at => insert_at}.to_json.html_safe %>);
|
10
12
|
<% else %>
|
11
13
|
ActiveScaffold.reload('<%= url_for render_parent_options %>');
|
12
14
|
<% end %>
|
@@ -2,7 +2,7 @@ module ActiveScaffold::Actions
|
|
2
2
|
module Core
|
3
3
|
def self.included(base)
|
4
4
|
base.class_eval do
|
5
|
-
|
5
|
+
prepend_before_filter :register_constraints_with_action_columns, :unless => :nested?
|
6
6
|
after_filter :clear_flashes
|
7
7
|
rescue_from ActiveScaffold::RecordNotAllowed, ActiveScaffold::ActionNotAllowed, :with => :deny_access
|
8
8
|
end
|
@@ -169,11 +169,12 @@ module ActiveScaffold::Actions
|
|
169
169
|
|
170
170
|
def new_model
|
171
171
|
model = beginning_of_chain
|
172
|
-
if model.columns_hash[column = model.inheritance_column]
|
173
|
-
build_options = {column.to_sym => active_scaffold_config.model_id} if nested? && nested.association && nested.association.collection?
|
172
|
+
if nested? && nested.association && nested.association.collection? && model.columns_hash[column = model.inheritance_column]
|
174
173
|
model_name = params.delete(column) # in new action inheritance_column must be in params
|
175
174
|
model_name ||= params[:record].delete(column) unless params[:record].blank? # in create action must be inside record key
|
176
|
-
|
175
|
+
model_name = model_name.camelize if model_name
|
176
|
+
model_name ||= active_scaffold_config.model.name
|
177
|
+
build_options = {column.to_sym => model_name} if model_name
|
177
178
|
end
|
178
179
|
model.respond_to?(:build) ? model.build(build_options || {}) : model.new
|
179
180
|
end
|
@@ -50,6 +50,10 @@ module ActiveScaffold::Actions
|
|
50
50
|
render :text => Hash.from_xml(response_object.to_xml(:only => list_columns_names)).to_yaml, :content_type => Mime::YAML, :status => response_status
|
51
51
|
end
|
52
52
|
|
53
|
+
def row_respond_to_html
|
54
|
+
render(:partial => 'row', :locals => {:record => @record})
|
55
|
+
end
|
56
|
+
|
53
57
|
def row_respond_to_js
|
54
58
|
render
|
55
59
|
end
|
@@ -3,7 +3,7 @@ module ActiveScaffold::Actions
|
|
3
3
|
|
4
4
|
def self.included(base)
|
5
5
|
base.before_filter :mark_authorized?, :only => :mark
|
6
|
-
base.
|
6
|
+
base.before_filter :assign_marked_records_to_model
|
7
7
|
base.helper_method :marked_records
|
8
8
|
end
|
9
9
|
|
@@ -14,9 +14,8 @@ module ActiveScaffold::Actions
|
|
14
14
|
do_demark
|
15
15
|
end
|
16
16
|
if marked_records.length > 0
|
17
|
-
link = "<a href=\"#{url_for(:action=>:mark, :id=>'', :mark_target => :scope)}\" data-method=\"post\" data-remote=\"true\">#{as_ :mark_all_records}</a>"
|
18
17
|
count = marked_records.length
|
19
|
-
flash[:info] = as_(:records_marked, :count => count, :model => active_scaffold_config.label(:count => count)
|
18
|
+
flash[:info] = as_(:records_marked, :count => count, :model => active_scaffold_config.label(:count => count))
|
20
19
|
end
|
21
20
|
respond_to_action(:mark)
|
22
21
|
end
|
@@ -103,7 +103,7 @@ module ActiveScaffold
|
|
103
103
|
# it's a single id
|
104
104
|
column.association.klass.find(value) if value and not value.empty?
|
105
105
|
elsif column.plural_association?
|
106
|
-
column_plural_assocation_value_from_value(column, value)
|
106
|
+
column_plural_assocation_value_from_value(column, Array(value))
|
107
107
|
elsif column.number? && [:i18n_number, :currency].include?(column.options[:format])
|
108
108
|
self.class.i18n_number_to_native_format(value)
|
109
109
|
else
|
@@ -135,11 +135,11 @@ module ActiveScaffold::DataStructures
|
|
135
135
|
@constrained_fields = Set.new
|
136
136
|
constrained_fields << association.foreign_key.to_sym unless association.belongs_to?
|
137
137
|
model.reflect_on_all_associations.each do |current|
|
138
|
-
if !current.belongs_to? && association.foreign_key == current.association_foreign_key
|
138
|
+
if !current.belongs_to? && association != current && association.foreign_key.to_s == current.association_foreign_key.to_s
|
139
139
|
constrained_fields << current.name.to_sym
|
140
140
|
@child_association = current if current.klass == @parent_model
|
141
141
|
end
|
142
|
-
if association.foreign_key == current.foreign_key
|
142
|
+
if association.foreign_key.to_s == current.foreign_key.to_s
|
143
143
|
# show columns for has_many and has_one child associationes
|
144
144
|
constrained_fields << current.name.to_sym if current.belongs_to?
|
145
145
|
if association.options[:as] and current.options[:polymorphic]
|
@@ -84,6 +84,8 @@ module ActiveScaffold
|
|
84
84
|
def condition_for_numeric(column, value)
|
85
85
|
if !value.is_a?(Hash)
|
86
86
|
["%{search_sql} = ?", condition_value_for_numeric(column, value)]
|
87
|
+
elsif ActiveScaffold::Finder::NullComparators.include?(value[:opt])
|
88
|
+
condition_for_null_type(column, value[:opt])
|
87
89
|
elsif value[:from].blank? or not ActiveScaffold::Finder::NumericComparators.include?(value[:opt])
|
88
90
|
nil
|
89
91
|
elsif value[:opt] == 'BETWEEN'
|
@@ -63,12 +63,8 @@ module ActiveScaffold
|
|
63
63
|
if nested_singular_association?
|
64
64
|
{:controller => nested.parent_scaffold.controller_path, :action => :row, :id => nested.parent_id}
|
65
65
|
elsif params[:parent_sti]
|
66
|
-
options =
|
67
|
-
|
68
|
-
options.merge(params.slice(:eid))
|
69
|
-
else
|
70
|
-
options.merge({:id => @record.id})
|
71
|
-
end
|
66
|
+
options = params_for(:controller => params[:parent_sti], :action => render_parent_action, :parent_sti => nil)
|
67
|
+
options.merge(:id => @record.id) if render_parent_action == :row
|
72
68
|
end
|
73
69
|
end
|
74
70
|
|
@@ -100,6 +100,12 @@ module ActiveScaffold
|
|
100
100
|
## Form input methods
|
101
101
|
##
|
102
102
|
|
103
|
+
def active_scaffold_translate_select_options(options)
|
104
|
+
options[:include_blank] = as_(options[:include_blank]) if options[:include_blank].is_a? Symbol
|
105
|
+
options[:prompt] = as_(options[:prompt]) if options[:prompt].is_a? Symbol
|
106
|
+
options
|
107
|
+
end
|
108
|
+
|
103
109
|
def active_scaffold_input_singular_association(column, html_options)
|
104
110
|
associated = @record.send(column.association.name)
|
105
111
|
|
@@ -113,6 +119,7 @@ module ActiveScaffold
|
|
113
119
|
html_options.update(column.options[:html_options] || {})
|
114
120
|
options.update(column.options)
|
115
121
|
html_options[:name] = "#{html_options[:name]}[]" if (html_options[:multiple] == true && !html_options[:name].to_s.ends_with?("[]"))
|
122
|
+
active_scaffold_translate_select_options(options)
|
116
123
|
select(:record, method, select_options.uniq, options, html_options)
|
117
124
|
end
|
118
125
|
|
@@ -153,6 +160,7 @@ module ActiveScaffold
|
|
153
160
|
end
|
154
161
|
html_options.update(column.options[:html_options] || {})
|
155
162
|
options.update(column.options)
|
163
|
+
active_scaffold_translate_select_options(options)
|
156
164
|
select(:record, column.name, options_for_select, options, html_options)
|
157
165
|
end
|
158
166
|
|
@@ -14,7 +14,7 @@ module ActiveScaffold
|
|
14
14
|
else
|
15
15
|
case search_ui
|
16
16
|
when :integer, :decimal, :float
|
17
|
-
"#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{format_number_value(controller.class.condition_value_for_numeric(column, value[:from]), column.options)} #{value[:opt] == 'BETWEEN' ? '- ' + format_number_value(controller.class.condition_value_for_numeric(column, value[:to]), column.options).to_s : ''}"
|
17
|
+
"#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{format_number_value(controller.class.condition_value_for_numeric(column, value[:from]), column.options) if value[:from].present?} #{value[:opt] == 'BETWEEN' ? '- ' + format_number_value(controller.class.condition_value_for_numeric(column, value[:to]), column.options).to_s : ''}"
|
18
18
|
when :string
|
19
19
|
opt = ActiveScaffold::Finder::StringComparators.index(value[:opt]) || value[:opt]
|
20
20
|
"#{column.active_record_class.human_attribute_name(column.name)} #{as_(opt).downcase} '#{value[:from]}' #{opt == 'BETWEEN' ? '- ' + value[:to].to_s : ''}"
|
@@ -335,7 +335,7 @@ module ActiveScaffold
|
|
335
335
|
if column.name == :as_marked
|
336
336
|
tag_options[:data] = {
|
337
337
|
:ie_mode => :inline_checkbox,
|
338
|
-
:ie_url => url_for(
|
338
|
+
:ie_url => url_for(params_for(:action => 'mark', :id => '__id__'))
|
339
339
|
}
|
340
340
|
else
|
341
341
|
tag_options[:data] = inplace_edit_data(column) if column.inplace_edit
|
@@ -124,9 +124,16 @@ module ActiveScaffold
|
|
124
124
|
url_options.delete(:search) if link.controller and link.controller.to_s != params[:controller]
|
125
125
|
url_options.merge! link.parameters if link.parameters
|
126
126
|
if link.dynamic_parameters.is_a?(Proc)
|
127
|
-
|
128
|
-
|
129
|
-
|
127
|
+
if record.nil?
|
128
|
+
url_options.merge! link.dynamic_parameters.call
|
129
|
+
elsif link.dynamic_parameters.arity == 0
|
130
|
+
ActiveSupport::Deprecation.warn("dynamic_parameters must be a block with an argument for member action links, instead of using @link_record")
|
131
|
+
@link_record = record
|
132
|
+
url_options.merge! self.instance_eval(&(link.dynamic_parameters))
|
133
|
+
@link_record = nil
|
134
|
+
else
|
135
|
+
url_options.merge! link.dynamic_parameters.call(record)
|
136
|
+
end
|
130
137
|
end
|
131
138
|
url_options_for_nested_link(link.column, record, link, url_options, options) if link.nested_link?
|
132
139
|
url_options_for_sti_link(link.column, record, link, url_options, options) unless record.nil? || active_scaffold_config.sti_children.nil?
|
@@ -172,7 +179,7 @@ module ActiveScaffold
|
|
172
179
|
id = "#{column.association.name}-#{record.id}" unless record.nil?
|
173
180
|
end if column && column.singular_association?
|
174
181
|
id = "#{id}-#{url_options[:batch_scope].downcase}" if url_options[:batch_scope]
|
175
|
-
action_id = "#{id_from_controller(url_options[:controller]) + '-' if url_options[:parent_controller]}#{url_options[:action].to_s}"
|
182
|
+
action_id = "#{id_from_controller(url_options[:controller]) + '-' if url_options[:parent_controller] || url_options[:controller] != controller.controller_path}#{url_options[:action].to_s}"
|
176
183
|
action_link_id(action_id, id)
|
177
184
|
end
|
178
185
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_scaffold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 47
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 3.2.
|
9
|
+
- 16
|
10
|
+
version: 3.2.16
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Many, see README
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-09-01 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
type: :development
|
@@ -29,8 +29,8 @@ dependencies:
|
|
29
29
|
- 0
|
30
30
|
version: "0"
|
31
31
|
version_requirements: *id001
|
32
|
-
prerelease: false
|
33
32
|
name: shoulda
|
33
|
+
prerelease: false
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
type: :development
|
36
36
|
requirement: &id002 !ruby/object:Gem::Requirement
|
@@ -45,8 +45,8 @@ dependencies:
|
|
45
45
|
- 0
|
46
46
|
version: 1.0.0
|
47
47
|
version_requirements: *id002
|
48
|
-
prerelease: false
|
49
48
|
name: bundler
|
49
|
+
prerelease: false
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
type: :development
|
52
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
@@ -59,8 +59,8 @@ dependencies:
|
|
59
59
|
- 0
|
60
60
|
version: "0"
|
61
61
|
version_requirements: *id003
|
62
|
-
prerelease: false
|
63
62
|
name: rcov
|
63
|
+
prerelease: false
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
type: :runtime
|
66
66
|
requirement: &id004 !ruby/object:Gem::Requirement
|
@@ -75,8 +75,8 @@ dependencies:
|
|
75
75
|
- 3
|
76
76
|
version: 3.1.3
|
77
77
|
version_requirements: *id004
|
78
|
-
prerelease: false
|
79
78
|
name: rails
|
79
|
+
prerelease: false
|
80
80
|
description: Save time and headaches, and create a more easily maintainable set of pages, with ActiveScaffold. ActiveScaffold handles all your CRUD (create, read, update, delete) user interface needs, leaving you more time to focus on more challenging (and interesting!) problems.
|
81
81
|
email: activescaffold@googlegroups.com
|
82
82
|
executables: []
|
@@ -276,7 +276,6 @@ files:
|
|
276
276
|
- lib/active_scaffold/extensions/action_controller_rendering.rb
|
277
277
|
- lib/active_scaffold/extensions/action_controller_rescueing.rb
|
278
278
|
- lib/active_scaffold/extensions/action_view_rendering.rb
|
279
|
-
- lib/active_scaffold/extensions/active_association_reflection.rb
|
280
279
|
- lib/active_scaffold/extensions/active_record_offset.rb
|
281
280
|
- lib/active_scaffold/extensions/array.rb
|
282
281
|
- lib/active_scaffold/extensions/cache_association.rb
|
@@ -443,7 +442,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
443
442
|
requirements: []
|
444
443
|
|
445
444
|
rubyforge_project:
|
446
|
-
rubygems_version: 1.8.
|
445
|
+
rubygems_version: 1.8.10
|
447
446
|
signing_key:
|
448
447
|
specification_version: 3
|
449
448
|
summary: Rails 3.1 Version of activescaffold supporting prototype and jquery
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# Bugfix: building an sti model from an association fails
|
2
|
-
# https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6306-collection-associations-build-method-not-supported-for-sti
|
3
|
-
# https://github.com/rails/rails/issues/815
|
4
|
-
# https://github.com/rails/rails/pull/1686
|
5
|
-
ActiveRecord::Reflection::AssociationReflection.class_eval do
|
6
|
-
def klass_with_sti(*opts)
|
7
|
-
sti_col = klass.inheritance_column
|
8
|
-
if sti_col and (h = opts.first).is_a? Hash and (passed_type = ( h[sti_col] || h[sti_col.to_sym] )) and (new_klass = active_record.send(:compute_type, passed_type)) < klass
|
9
|
-
new_klass
|
10
|
-
else
|
11
|
-
klass
|
12
|
-
end
|
13
|
-
end
|
14
|
-
def build_association(*opts, &block)
|
15
|
-
@original_build_association_called = true # FIXME: remove when 3.1 support is dropped
|
16
|
-
klass_with_sti(*opts).new(*opts, &block)
|
17
|
-
end
|
18
|
-
def create_association(*opts, &block)
|
19
|
-
@original_build_association_called = true # FIXME: remove when 3.1 support is dropped
|
20
|
-
klass_with_sti(*opts).create(*opts, &block)
|
21
|
-
end
|
22
|
-
end
|