adminpanel 2.4.3 → 2.5.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 +4 -4
- data/.travis.yml +1 -0
- data/README.md +16 -16
- data/adminpanel.gemspec +9 -8
- data/app/assets/javascripts/adminpanel/application.js +4 -0
- data/app/assets/javascripts/adminpanel/bootstrap-wysihtml5.js +2 -4
- data/app/assets/javascripts/adminpanel/sortable.js.coffee +27 -0
- data/app/assets/stylesheets/adminpanel/application.css +1 -0
- data/app/assets/stylesheets/adminpanel/sortable.css.scss.erb +13 -0
- data/app/controllers/adminpanel/application_controller.rb +0 -1
- data/app/controllers/adminpanel/sessions_controller.rb +5 -2
- data/app/controllers/concerns/adminpanel/rest_actions.rb +24 -22
- data/app/controllers/concerns/adminpanel/sortable_actions.rb +3 -20
- data/app/helpers/adminpanel/breadcrumbs_helper.rb +6 -5
- data/app/helpers/adminpanel/router_helper.rb +9 -3
- data/app/helpers/adminpanel/shared_pages_helper.rb +1 -1
- data/app/models/concerns/adminpanel/base.rb +34 -11
- data/app/models/concerns/adminpanel/sitemap.rb +0 -1
- data/app/models/concerns/adminpanel/sortable.rb +33 -30
- data/app/models/concerns/adminpanel/sortable_gallery.rb +90 -0
- data/app/views/adminpanel/form/_adminpanel_file_field.html.erb +1 -1
- data/app/views/adminpanel/templates/index.html.erb +41 -13
- data/app/views/adminpanel/templates/show.html.erb +33 -13
- data/config/initializers/adminpanel/carrierwave_mini_magick_quality.rb +11 -0
- data/config/locales/en.yml +3 -7
- data/config/locales/es.yml +1 -8
- data/config/routes.rb +6 -8
- data/lib/adminpanel.rb +9 -8
- data/lib/adminpanel/version.rb +1 -1
- data/lib/generators/adminpanel/custom_errors/custom_errors_generator.rb +37 -0
- data/lib/generators/adminpanel/custom_errors/templates/errors_controller.rb +14 -0
- data/lib/generators/adminpanel/custom_errors/templates/show.html.erb +1 -0
- data/lib/generators/adminpanel/gallery/templates/gallery_template.rb +8 -3
- data/lib/generators/adminpanel/gallery/templates/uploader.rb +4 -1
- data/lib/generators/adminpanel/initialize/initialize_generator.rb +0 -12
- data/lib/generators/adminpanel/initialize/templates/adminpanel_setup.rb +1 -2
- data/lib/generators/adminpanel/resource/resource_generator.rb +29 -8
- data/lib/generators/adminpanel/resource/resource_generator_helper.rb +34 -7
- data/lib/generators/adminpanel/resource/templates/adminpanel_resource_template.rb +7 -2
- data/lib/tasks/adminpanel/adminpanel.rake +19 -61
- data/test/dummy/app/models/adminpanel/file_resourcefile.rb +1 -1
- data/test/dummy/app/models/adminpanel/gallery.rb +9 -4
- data/test/dummy/app/models/adminpanel/galleryfile.rb +2 -2
- data/test/dummy/app/models/adminpanel/photo.rb +1 -1
- data/test/dummy/app/models/adminpanel/product.rb +0 -4
- data/test/dummy/config/initializers/adminpanel_setup.rb +1 -1
- data/test/dummy/test/fixtures/adminpanel/galleryfiles.yml +24 -0
- data/test/features/shared/concerns/sortable_gallery_ui_test.rb +25 -0
- data/test/features/shared/concerns/sortable_test.rb +4 -4
- data/test/features/shared/form/{belongs_to_non_category_modal_test.rb → belongs_to_remote_test.rb} +1 -1
- data/test/features/shared/form/{has_many_through_non_category_modal_test.rb → has_many_through_remote_test.rb} +1 -1
- data/test/generators/dump_generator_test.rb +1 -13
- data/test/generators/gallery_generator_test.rb +1 -1
- data/test/generators/initialize_generator_test.rb +1 -9
- data/test/generators/resource_generator_test.rb +21 -1
- data/test/helpers/router_helper_test.rb +0 -4
- data/test/models/adminpanel/sortable_gallery_unit_test.rb +118 -0
- data/test/models/adminpanel/sortable_unit_test.rb +75 -0
- data/test/tasks/adminpanel_rake_test.rb +1 -1
- metadata +86 -85
- data/app/assets/images/adminpanel/loguito.png +0 -0
- data/app/controllers/adminpanel/categories_controller.rb +0 -52
- data/app/controllers/concerns/adminpanel/galleryzable_actions.rb +0 -34
- data/app/models/concerns/adminpanel/galleryzation.rb +0 -78
- data/app/views/adminpanel/categories/_categories_table.html.erb +0 -48
- data/app/views/adminpanel/categories/_category_form.html.erb +0 -33
- data/app/views/adminpanel/categories/create.js.erb +0 -6
- data/app/views/adminpanel/categories/index.html.erb +0 -63
- data/app/views/adminpanel/categories/new.js.erb +0 -5
- data/app/views/adminpanel/icons/_move_to_better.html.erb +0 -17
- data/app/views/adminpanel/icons/_move_to_worst.html.erb +0 -18
- data/app/views/adminpanel/shared/_gallery_entries.html.erb +0 -11
- data/app/views/adminpanel/shared/_index_records.html.erb +0 -32
- data/app/views/adminpanel/templates/gallery_entries.js.erb +0 -1
- data/app/views/adminpanel/templates/index_records.js.erb +0 -1
- data/lib/generators/adminpanel/initialize/templates/category_template.rb +0 -45
- data/lib/generators/adminpanel/initialize/templates/create_adminpanel_categories_table.rb +0 -11
- data/test/features/categories/categories_index_test.rb +0 -31
- data/test/features/shared/concerns/galleryzable_test.rb +0 -22
- data/test/features/shared/form/belongs_to_category_modal_test.rb +0 -35
- data/test/features/shared/form/has_many_through_category_modal_test.rb +0 -35
- data/test/models/adminpanel/galleryzable_test.rb +0 -28
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
namespace :adminpanel do
|
|
2
|
-
desc
|
|
2
|
+
desc 'Interact with adminpanel models :D'
|
|
3
3
|
|
|
4
4
|
task :section, [:name, :section, :type] => :environment do |t, args|
|
|
5
5
|
args.with_defaults(:section => "home", :name => "greeting", :type => "")
|
|
@@ -8,12 +8,12 @@ namespace :adminpanel do
|
|
|
8
8
|
order = Adminpanel::Section.find_by(:page => page_name)
|
|
9
9
|
|
|
10
10
|
s = Adminpanel::Section.new(
|
|
11
|
-
:
|
|
12
|
-
:
|
|
13
|
-
:
|
|
14
|
-
:
|
|
15
|
-
:
|
|
16
|
-
:
|
|
11
|
+
name: args[:name].titleize,
|
|
12
|
+
has_description: false,
|
|
13
|
+
description: "",
|
|
14
|
+
key: (args[:name].downcase.tr(' ','_')),
|
|
15
|
+
page: page_name,
|
|
16
|
+
has_image: false
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
if order.nil?
|
|
@@ -33,56 +33,36 @@ namespace :adminpanel do
|
|
|
33
33
|
s.save
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
task :
|
|
36
|
+
task user: :environment do |t|
|
|
37
37
|
characters = []
|
|
38
38
|
characters.concat(("a".."z").to_a)
|
|
39
39
|
characters.concat(("A".."Z").to_a)
|
|
40
40
|
characters.concat((0..9).to_a)
|
|
41
41
|
characters.concat(%w[! @ \# $ % ^ & * , _ - + =])
|
|
42
|
-
password =
|
|
42
|
+
password = ''
|
|
43
43
|
8.times do
|
|
44
44
|
password = password + "#{characters.sample}"
|
|
45
45
|
end
|
|
46
|
-
puts "Creating/overwriting webmaster@codn.
|
|
47
|
-
user = Adminpanel::User.find_by_email('webmaster@codn.
|
|
46
|
+
puts "Creating/overwriting webmaster@codn.mx with password #{password}" unless Rails.env.test?
|
|
47
|
+
user = Adminpanel::User.find_by_email('webmaster@codn.mx')
|
|
48
48
|
if !user.nil?
|
|
49
49
|
user.delete
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
role = Adminpanel::Role.find_by_name(
|
|
52
|
+
role = Adminpanel::Role.find_by_name('Admin')
|
|
53
53
|
if role.nil?
|
|
54
|
-
role = Adminpanel::Role.new(:
|
|
54
|
+
role = Adminpanel::Role.new(name: 'Admin')
|
|
55
55
|
role.save
|
|
56
56
|
end
|
|
57
57
|
Adminpanel::User.new(
|
|
58
|
-
:
|
|
59
|
-
:
|
|
60
|
-
:
|
|
61
|
-
:
|
|
62
|
-
:
|
|
58
|
+
email: 'webmaster@codn.mx',
|
|
59
|
+
name: 'Webmaster',
|
|
60
|
+
password: password,
|
|
61
|
+
password_confirmation: password,
|
|
62
|
+
role_id: role.id
|
|
63
63
|
).save
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
task :dump_sections => :environment do |t|
|
|
67
|
-
puts "Dumping adminpanel_sections table into db/seeds.rb"
|
|
68
|
-
File.open("#{Rails.root.join('db', 'seeds.rb')}", "w") do |f|
|
|
69
|
-
f << "Adminpanel::Section.delete_all\n"
|
|
70
|
-
Adminpanel::Section.all.each do |section|
|
|
71
|
-
f << "#{creation_command_section(section)}"
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
task :dump_categories => :environment do |t|
|
|
77
|
-
puts "Dumping adminpanel_categories table into db/seeds.rb"
|
|
78
|
-
File.open("#{Rails.root.join('db', 'seeds.rb')}", "w") do |f|
|
|
79
|
-
f << "Adminpanel::Section.delete_all\n"
|
|
80
|
-
Adminpanel::Section.all.each do |section|
|
|
81
|
-
f << "#{creation_command_categories(section)}"
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
66
|
task :populate, [:times, :model, :attributes] => :environment do |t, args|
|
|
87
67
|
require 'faker'
|
|
88
68
|
I18n.reload!
|
|
@@ -159,28 +139,6 @@ end
|
|
|
159
139
|
|
|
160
140
|
private
|
|
161
141
|
|
|
162
|
-
def creation_command_section(section)
|
|
163
|
-
"Adminpanel::Section.new(\n" +
|
|
164
|
-
"\t:name => \"#{section.name}\",\n" +
|
|
165
|
-
"\t:has_description => #{section.has_description},\n" +
|
|
166
|
-
"\t:description => \"#{escape_double_quotes(section.description)}\",\n" +
|
|
167
|
-
"\t:key => \"#{section.key}\",\n" +
|
|
168
|
-
"\t:page => \"#{section.page}\",\n" +
|
|
169
|
-
"\t:has_image => #{section.has_image}\n" +
|
|
170
|
-
").save\n"
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def creation_command_category(category)
|
|
174
|
-
"Adminpanel::Category.new(\n" +
|
|
175
|
-
"\t:name => \"#{escape_double_quotes(category.name)}\",\n" +
|
|
176
|
-
"\t:model => \"#{category.model}\"\n" +
|
|
177
|
-
").save\n"
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def escape_double_quotes(string)
|
|
181
|
-
string.gsub('"', '\\"')
|
|
182
|
-
end
|
|
183
|
-
|
|
184
142
|
def change_dates(instance)
|
|
185
143
|
date = rand(Date.parse('2010-01-01')..Date.today)
|
|
186
144
|
instance.update_attribute(:created_at, date)
|
|
@@ -189,5 +147,5 @@ private
|
|
|
189
147
|
|
|
190
148
|
def float_random(min_number, max_number)
|
|
191
149
|
width = max_number - min_number
|
|
192
|
-
return (rand*width)+min_number
|
|
150
|
+
return (rand*width) + min_number
|
|
193
151
|
end
|
|
@@ -5,6 +5,8 @@ module Adminpanel
|
|
|
5
5
|
|
|
6
6
|
mount_uploader :file, Adminpanel::PhotoUploader
|
|
7
7
|
|
|
8
|
+
mount_images :galleryfiles
|
|
9
|
+
|
|
8
10
|
def name
|
|
9
11
|
file
|
|
10
12
|
end
|
|
@@ -13,10 +15,16 @@ module Adminpanel
|
|
|
13
15
|
[
|
|
14
16
|
{
|
|
15
17
|
'file' => {
|
|
16
|
-
'type' => '
|
|
18
|
+
'type' => 'text',
|
|
17
19
|
'label' => 'file',
|
|
18
20
|
|
|
19
21
|
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
'galleryfiles' => {
|
|
25
|
+
'type' => 'adminpanel_file_fields',
|
|
26
|
+
'label' => 'images for this gallery'
|
|
27
|
+
}
|
|
20
28
|
}
|
|
21
29
|
]
|
|
22
30
|
end
|
|
@@ -25,8 +33,5 @@ module Adminpanel
|
|
|
25
33
|
'Galeria'
|
|
26
34
|
end
|
|
27
35
|
|
|
28
|
-
def self.gallery_children
|
|
29
|
-
'galleryfiles'
|
|
30
|
-
end
|
|
31
36
|
end
|
|
32
37
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Adminpanel
|
|
2
2
|
class Galleryfile < ActiveRecord::Base
|
|
3
3
|
include Adminpanel::Base
|
|
4
|
-
include Adminpanel::
|
|
4
|
+
include Adminpanel::SortableGallery
|
|
5
5
|
|
|
6
6
|
belongs_to :gallery
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ module Adminpanel
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def self.display_name
|
|
15
|
-
'
|
|
15
|
+
'galleryfile'
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
end
|
|
@@ -16,3 +16,27 @@ third:
|
|
|
16
16
|
position: 3
|
|
17
17
|
created_at: <%= Date.today %>
|
|
18
18
|
updated_at: <%= Date.today %>
|
|
19
|
+
fourth:
|
|
20
|
+
file: hipster.jpg
|
|
21
|
+
gallery: one
|
|
22
|
+
position: 4
|
|
23
|
+
created_at: <%= Date.today %>
|
|
24
|
+
updated_at: <%= Date.today %>
|
|
25
|
+
fifth:
|
|
26
|
+
file: hipster.jpg
|
|
27
|
+
gallery: one
|
|
28
|
+
position: 5
|
|
29
|
+
created_at: <%= Date.today %>
|
|
30
|
+
updated_at: <%= Date.today %>
|
|
31
|
+
first_2:
|
|
32
|
+
file: hipster.jpg
|
|
33
|
+
gallery: two
|
|
34
|
+
position: 1
|
|
35
|
+
created_at: <%= Date.today %>
|
|
36
|
+
updated_at: <%= Date.today %>
|
|
37
|
+
second_2:
|
|
38
|
+
file: hipster.jpg
|
|
39
|
+
gallery: two
|
|
40
|
+
position: 2
|
|
41
|
+
created_at: <%= Date.today %>
|
|
42
|
+
updated_at: <%= Date.today %>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class SortableGalleryUiTest < ViewCase
|
|
4
|
+
fixtures :all
|
|
5
|
+
|
|
6
|
+
setup :sign_in
|
|
7
|
+
teardown :teardown
|
|
8
|
+
|
|
9
|
+
def test_including_draggable_td
|
|
10
|
+
skip '😪'
|
|
11
|
+
visit adminpanel.gallery_path(adminpanel_galleries(:one))
|
|
12
|
+
|
|
13
|
+
p page.body
|
|
14
|
+
|
|
15
|
+
# assert for sortable stuff
|
|
16
|
+
assert_selector 'td.draggable.img'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
|
|
21
|
+
def sign_in
|
|
22
|
+
visit adminpanel.signin_path
|
|
23
|
+
login
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -5,14 +5,14 @@ class SortableTest < ViewCase
|
|
|
5
5
|
|
|
6
6
|
setup :sign_in
|
|
7
7
|
teardown :teardown
|
|
8
|
+
|
|
8
9
|
def test_including_of_position_and_default_icons
|
|
9
10
|
visit adminpanel.galleries_path
|
|
10
11
|
assert_link 'Crear Galeria'
|
|
11
12
|
|
|
12
|
-
#
|
|
13
|
-
assert_selector '
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
# test for draggable element
|
|
14
|
+
assert_selector 'td.draggable'
|
|
15
|
+
|
|
16
16
|
assert_selector 'i.fa.fa-pencil'
|
|
17
17
|
assert_selector 'i.fa.fa-trash-o'
|
|
18
18
|
assert_selector 'i.fa.fa-search-plus'
|
|
@@ -10,17 +10,13 @@ class DumpGeneratorTest < Rails::Generators::TestCase
|
|
|
10
10
|
assert_no_file( 'db/users.json' )
|
|
11
11
|
assert( Adminpanel::User.count > 0 ) #ensure there's something in adminpanel_users
|
|
12
12
|
|
|
13
|
-
# Dir.mkdir("#{Rails.root.join('tmp/generators')}/db")
|
|
14
|
-
# File.open("#{Rails.root.join('tmp/generators')}/db/seeds.rb", 'w') do
|
|
15
|
-
# "\n"
|
|
16
|
-
# end
|
|
17
13
|
run_generator %w(
|
|
18
14
|
user
|
|
19
15
|
-i
|
|
20
16
|
false
|
|
21
17
|
)
|
|
22
18
|
|
|
23
|
-
#assert has user fields in json format, in an array
|
|
19
|
+
#assert has user fields in json format, in an array dumped
|
|
24
20
|
assert_file(
|
|
25
21
|
'db/users.json',
|
|
26
22
|
/\[{/,
|
|
@@ -29,14 +25,6 @@ class DumpGeneratorTest < Rails::Generators::TestCase
|
|
|
29
25
|
/"email":"user@example.com"/,
|
|
30
26
|
/"role_id":/
|
|
31
27
|
)
|
|
32
|
-
# haven't been able to assert injection :(
|
|
33
|
-
# assert_file(
|
|
34
|
-
# 'db/seeds.rb',
|
|
35
|
-
# /objects = JSON.parse(open("#{Rails.root}\/db\/users.json").read)/,
|
|
36
|
-
# /objects.each do |element|/,
|
|
37
|
-
# / Adminpanel::User.create element/,
|
|
38
|
-
# /end/
|
|
39
|
-
# )
|
|
40
28
|
end
|
|
41
29
|
|
|
42
30
|
def test_runs_without_errors
|
|
@@ -16,22 +16,14 @@ class InitializeGeneratorTest < Rails::Generators::TestCase
|
|
|
16
16
|
assert_file 'config/initializers/adminpanel_setup.rb'
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def test_the_generation_of_the_categories_files
|
|
20
|
-
run_generator
|
|
21
|
-
assert_migration 'db/migrate/create_adminpanel_categories_table.rb'
|
|
22
|
-
assert_file 'app/models/adminpanel/category.rb'
|
|
23
|
-
end
|
|
24
|
-
|
|
25
19
|
def test_the_generation_of_the_section_uploader
|
|
26
20
|
run_generator
|
|
27
21
|
assert_file 'app/uploaders/adminpanel/section_uploader.rb'
|
|
28
22
|
end
|
|
29
23
|
|
|
30
24
|
def test_the_not_generation_of_files
|
|
31
|
-
run_generator %w( -
|
|
25
|
+
run_generator %w( -u true -m true -p true )
|
|
32
26
|
assert_no_file 'config/initializers/adminpanel_setup.rb'
|
|
33
|
-
assert_no_file 'app/models/adminpanel/category.rb'
|
|
34
|
-
assert_no_migration 'db/migrate/create_adminpanel_categories_table.rb'
|
|
35
27
|
assert_no_migration 'db/migrate/create_adminpanel_tables'
|
|
36
28
|
assert_no_file 'app/uploaders/adminpanel/section_uploader.rb'
|
|
37
29
|
end
|
|
@@ -101,6 +101,7 @@ class ResourceGeneratorTest < Rails::Generators::TestCase
|
|
|
101
101
|
description:wysiwyg
|
|
102
102
|
number:float
|
|
103
103
|
flag:boolean
|
|
104
|
+
avatar:file
|
|
104
105
|
quantity:integer
|
|
105
106
|
date:datepicker
|
|
106
107
|
categories:has_many
|
|
@@ -120,6 +121,8 @@ class ResourceGeneratorTest < Rails::Generators::TestCase
|
|
|
120
121
|
/'type' => 'text_field',/,
|
|
121
122
|
/'flag' => {/,
|
|
122
123
|
/'type' => 'boolean',/,
|
|
124
|
+
/'avatar' => {/,
|
|
125
|
+
/'type' => 'file_field',/,
|
|
123
126
|
/'quantity' => {/,
|
|
124
127
|
/'type' => 'number_field',/,
|
|
125
128
|
/'date' => {/,
|
|
@@ -160,11 +163,28 @@ class ResourceGeneratorTest < Rails::Generators::TestCase
|
|
|
160
163
|
/'type' => 'has_many'/,
|
|
161
164
|
/'model' => 'Adminpanel::Post'/,
|
|
162
165
|
/'category_ids' => {/,
|
|
163
|
-
/'type' => 'has_many'/,
|
|
164
166
|
/'model' => 'Adminpanel::Category'/
|
|
165
167
|
)
|
|
166
168
|
end
|
|
167
169
|
|
|
170
|
+
def test_generating_with_single_attachment_file
|
|
171
|
+
run_generator %w(
|
|
172
|
+
monkey
|
|
173
|
+
avatar:file
|
|
174
|
+
)
|
|
175
|
+
assert_file(
|
|
176
|
+
'app/models/adminpanel/monkey.rb',
|
|
177
|
+
/def name/,
|
|
178
|
+
/mount_uploader :avatar, MonkeyAvatarUploader/,
|
|
179
|
+
/'avatar' => {/,
|
|
180
|
+
/'type' => 'file_field'/
|
|
181
|
+
)
|
|
182
|
+
assert_file(
|
|
183
|
+
'app/uploaders/adminpanel/monkey_avatar_uploader.rb',
|
|
184
|
+
/class MonkeyAvatarUploader </
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
168
188
|
def test_that_runs_without_errors
|
|
169
189
|
assert_nothing_raised do
|
|
170
190
|
run_generator ["doll", ['name']]
|
|
@@ -5,10 +5,6 @@ class RouterHelperTest < ActionView::TestCase
|
|
|
5
5
|
|
|
6
6
|
fixtures :all
|
|
7
7
|
|
|
8
|
-
def test_get_gallery_childen
|
|
9
|
-
assert_equal 'galleryfiles', get_gallery_children(:gallery)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
8
|
def test_resource_parameters
|
|
13
9
|
assert_equal( { path: 'categorias' }, resources_parameters(:categories) )
|
|
14
10
|
assert_equal( { path: 'articulo-espacios-mayusculas-y-acentos' }, resources_parameters(:items) )
|