katalyst-koi 4.5.0.beta.1 → 4.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/app/assets/builds/koi/admin.css +34 -4
- data/app/assets/builds/koi/admin.css.map +1 -1
- data/app/assets/stylesheets/koi/components/_index-table.scss +54 -3
- data/app/components/koi/summary_list/attachment_component.rb +11 -1
- data/app/components/koi/summary_list/base.rb +15 -1
- data/app/components/koi/summary_list/item_component.rb +0 -7
- data/app/components/koi/summary_list/rich_text_component.rb +0 -3
- data/app/components/koi/summary_list_component.rb +14 -14
- data/app/components/koi/tables/body.rb +117 -32
- data/app/components/koi/tables/body_row_component.rb +116 -18
- data/app/components/koi/tables/header.rb +51 -1
- data/app/components/koi/tables/header_cell_component.rb +30 -0
- data/app/components/koi/tables/header_row_component.rb +182 -20
- data/app/helpers/koi/date_helper.rb +18 -28
- data/lib/generators/koi/admin_controller/templates/controller.rb.tt +6 -7
- data/lib/generators/koi/admin_controller/templates/controller_spec.rb.tt +4 -4
- data/lib/generators/koi/admin_views/admin_views_generator.rb +6 -4
- data/lib/generators/koi/admin_views/templates/_record.html+row.erb.tt +1 -1
- data/lib/koi/config.rb +3 -0
- data/lib/koi/form_builder.rb +2 -2
- metadata +4 -4
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
|
4
|
+
|
|
3
5
|
module Koi
|
|
4
6
|
module Tables
|
|
5
7
|
module Body
|
|
@@ -11,47 +13,117 @@ module Koi
|
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
# Formats the value as a date
|
|
14
|
-
#
|
|
16
|
+
# @param format [String] date format, defaults to :admin
|
|
17
|
+
# @param relative [Boolean] if true, the date may be(if within 5 days) shown as a relative date
|
|
15
18
|
class DateComponent < BodyCellComponent
|
|
16
|
-
|
|
19
|
+
include Koi::DateHelper
|
|
20
|
+
|
|
21
|
+
def initialize(table, record, attribute, format: :admin, relative: true, **options)
|
|
17
22
|
super(table, record, attribute, **options)
|
|
18
23
|
|
|
19
|
-
@format
|
|
24
|
+
@format = format
|
|
25
|
+
@relative = relative
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def value
|
|
29
|
+
super&.to_date
|
|
20
30
|
end
|
|
21
31
|
|
|
22
32
|
def rendered_value
|
|
23
|
-
|
|
33
|
+
@relative ? relative_time : absolute_time
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def absolute_time
|
|
39
|
+
value.present? ? I18n.l(value, format: @format) : ""
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def relative_time
|
|
43
|
+
if value.blank?
|
|
44
|
+
""
|
|
45
|
+
else
|
|
46
|
+
days_ago_in_words(value)&.capitalize || absolute_time
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def default_html_attributes
|
|
51
|
+
@relative && value.present? && days_ago_in_words(value).present? ? { title: absolute_time } : {}
|
|
24
52
|
end
|
|
25
53
|
end
|
|
26
54
|
|
|
27
55
|
# Formats the value as a datetime
|
|
28
|
-
#
|
|
56
|
+
# @param format [String] datetime format, defaults to :admin
|
|
57
|
+
# @param relative [Boolean] if true, the datetime may be(if today) shown as a relative date/time
|
|
29
58
|
class DatetimeComponent < BodyCellComponent
|
|
30
|
-
|
|
59
|
+
include ActionView::Helpers::DateHelper
|
|
60
|
+
|
|
61
|
+
def initialize(table, record, attribute, format: :admin, relative: true, **options)
|
|
31
62
|
super(table, record, attribute, **options)
|
|
32
63
|
|
|
33
|
-
@format
|
|
64
|
+
@format = format
|
|
65
|
+
@relative = relative
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def value
|
|
69
|
+
super&.to_datetime
|
|
34
70
|
end
|
|
35
71
|
|
|
36
72
|
def rendered_value
|
|
37
|
-
|
|
73
|
+
@relative ? relative_time : absolute_time
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def absolute_time
|
|
79
|
+
value.present? ? I18n.l(value, format: @format) : ""
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def today?
|
|
83
|
+
value.to_date == Date.current
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def relative_time
|
|
87
|
+
return "" if value.blank?
|
|
88
|
+
|
|
89
|
+
if today?
|
|
90
|
+
if value > DateTime.current
|
|
91
|
+
"#{distance_of_time_in_words(value, DateTime.current)} from now".capitalize
|
|
92
|
+
else
|
|
93
|
+
"#{distance_of_time_in_words(value, DateTime.current)} ago".capitalize
|
|
94
|
+
end
|
|
95
|
+
else
|
|
96
|
+
absolute_time
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def default_html_attributes
|
|
101
|
+
@relative && today? ? { title: absolute_time } : {}
|
|
38
102
|
end
|
|
39
103
|
end
|
|
40
104
|
|
|
41
105
|
# Formats the value as a money value
|
|
42
|
-
#
|
|
106
|
+
#
|
|
107
|
+
# The value is expected to be in cents.
|
|
43
108
|
# Adds a class to the cell to allow for custom styling
|
|
44
|
-
class
|
|
109
|
+
class CurrencyComponent < BodyCellComponent
|
|
110
|
+
def initialize(table, record, attribute, options: {}, **html_attributes)
|
|
111
|
+
super(table, record, attribute, **html_attributes)
|
|
112
|
+
|
|
113
|
+
@options = options
|
|
114
|
+
end
|
|
115
|
+
|
|
45
116
|
def rendered_value
|
|
46
|
-
value.present? ? number_to_currency(value / 100.0) : ""
|
|
117
|
+
value.present? ? number_to_currency(value / 100.0, @options) : ""
|
|
47
118
|
end
|
|
48
119
|
|
|
49
120
|
def default_html_attributes
|
|
50
|
-
|
|
121
|
+
super.merge_html(class: "type-currency")
|
|
51
122
|
end
|
|
52
123
|
end
|
|
53
124
|
|
|
54
125
|
# Formats the value as a number
|
|
126
|
+
#
|
|
55
127
|
# Adds a class to the cell to allow for custom styling
|
|
56
128
|
class NumberComponent < BodyCellComponent
|
|
57
129
|
def rendered_value
|
|
@@ -59,51 +131,58 @@ module Koi
|
|
|
59
131
|
end
|
|
60
132
|
|
|
61
133
|
def default_html_attributes
|
|
62
|
-
|
|
134
|
+
super.merge_html(class: "type-number")
|
|
63
135
|
end
|
|
64
136
|
end
|
|
65
137
|
|
|
66
138
|
# Displays the plain text for rich text content
|
|
139
|
+
#
|
|
67
140
|
# Adds a title attribute to allow for hover over display of the full content
|
|
68
141
|
class RichTextComponent < BodyCellComponent
|
|
69
|
-
def rendered_value
|
|
70
|
-
value.to_plain_text
|
|
71
|
-
end
|
|
72
|
-
|
|
73
142
|
def default_html_attributes
|
|
74
|
-
{ title:
|
|
143
|
+
{ title: value.to_plain_text }
|
|
75
144
|
end
|
|
76
145
|
end
|
|
77
146
|
|
|
78
147
|
# Displays a link to the record
|
|
79
148
|
# The link text is the value of the attribute
|
|
80
|
-
# @
|
|
149
|
+
# @see Koi::Tables::BodyRowComponent#link
|
|
81
150
|
class LinkComponent < BodyCellComponent
|
|
82
|
-
def initialize(table, record, attribute, url:
|
|
83
|
-
super(table, record, attribute, **
|
|
151
|
+
def initialize(table, record, attribute, url:, link: {}, **options)
|
|
152
|
+
super(table, record, attribute, **options)
|
|
84
153
|
|
|
85
|
-
@
|
|
154
|
+
@url = url
|
|
155
|
+
@link_options = link
|
|
86
156
|
end
|
|
87
157
|
|
|
88
158
|
def call
|
|
89
159
|
content # ensure content is set before rendering options
|
|
90
160
|
|
|
91
|
-
link = content.present? && url.present? ? link_to(
|
|
161
|
+
link = content.present? && url.present? ? link_to(content, url, @link_options) : content.to_s
|
|
92
162
|
content_tag(@type, link, **html_attributes)
|
|
93
163
|
end
|
|
94
164
|
|
|
95
165
|
def url
|
|
96
|
-
@url
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
166
|
+
case @url
|
|
167
|
+
when Symbol
|
|
168
|
+
# helpers are not available until the component is rendered
|
|
169
|
+
@url = helpers.public_send(@url, record)
|
|
170
|
+
when Proc
|
|
171
|
+
@url = @url.call(record)
|
|
172
|
+
else
|
|
173
|
+
@url
|
|
174
|
+
end
|
|
101
175
|
end
|
|
102
176
|
end
|
|
103
177
|
|
|
104
|
-
# Shows
|
|
105
|
-
#
|
|
106
|
-
|
|
178
|
+
# Shows an attachment
|
|
179
|
+
#
|
|
180
|
+
# The value is expected to be an ActiveStorage attachment
|
|
181
|
+
#
|
|
182
|
+
# If it is representable, shows as a image tag using a default variant named :thumb.
|
|
183
|
+
#
|
|
184
|
+
# Otherwise shows as a link to download.
|
|
185
|
+
class AttachmentComponent < BodyCellComponent
|
|
107
186
|
def initialize(table, record, attribute, variant: :thumb, **options)
|
|
108
187
|
super(table, record, attribute, **options)
|
|
109
188
|
|
|
@@ -111,7 +190,13 @@ module Koi
|
|
|
111
190
|
end
|
|
112
191
|
|
|
113
192
|
def rendered_value
|
|
114
|
-
|
|
193
|
+
if value.try(:representable?)
|
|
194
|
+
image_tag(@variant.nil? ? value : value.variant(@variant))
|
|
195
|
+
elsif value.try(:attached?)
|
|
196
|
+
link_to value.blob.filename, rails_blob_path(value, disposition: :attachment)
|
|
197
|
+
else
|
|
198
|
+
""
|
|
199
|
+
end
|
|
115
200
|
end
|
|
116
201
|
end
|
|
117
202
|
end
|
|
@@ -4,40 +4,138 @@ module Koi
|
|
|
4
4
|
module Tables
|
|
5
5
|
# Custom body row component, in order to override the default body cell component
|
|
6
6
|
class BodyRowComponent < Katalyst::Tables::BodyRowComponent
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
# Generates a column from boolean values rendered as "Yes" or "No".
|
|
8
|
+
#
|
|
9
|
+
# @param method [Symbol] the method to call on the record
|
|
10
|
+
# @param attributes [Hash] HTML attributes to be added to the cell
|
|
11
|
+
# @param block [Proc] optional block to alter the cell content
|
|
12
|
+
# @return [void]
|
|
13
|
+
#
|
|
14
|
+
# @example Render a boolean column indicating whether the record is active
|
|
15
|
+
# <% row.boolean :active %> # => <td>Yes</td>
|
|
16
|
+
def boolean(method, **attributes, &block)
|
|
17
|
+
with_column(Body::BooleanComponent.new(@table, @record, method, **attributes), &block)
|
|
9
18
|
end
|
|
10
19
|
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
# Generates a column from date values rendered using I18n.l.
|
|
21
|
+
# The default format is :admin, but it can be overridden.
|
|
22
|
+
#
|
|
23
|
+
# @param method [Symbol] the method to call on the record
|
|
24
|
+
# @param format [Symbol] the I18n date format to use when rendering
|
|
25
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
26
|
+
# @param block [Proc] optional block to alter the cell content
|
|
27
|
+
# @return [void]
|
|
28
|
+
#
|
|
29
|
+
# @example Render a date column describing when the record was created
|
|
30
|
+
# <% row.date :created_at %> # => <td>29 Feb 2024</td>
|
|
31
|
+
def date(method, format: :admin, **attributes, &block)
|
|
32
|
+
with_column(Body::DateComponent.new(@table, @record, method, format:, **attributes), &block)
|
|
13
33
|
end
|
|
14
34
|
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
# Generates a column from datetime values rendered using I18n.l.
|
|
36
|
+
# The default format is :admin, but it can be overridden.
|
|
37
|
+
#
|
|
38
|
+
# @param method [Symbol] the method to call on the record
|
|
39
|
+
# @param format [Symbol] the I18n datetime format to use when rendering
|
|
40
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
41
|
+
# @param block [Proc] optional block to alter the cell content
|
|
42
|
+
# @return [void]
|
|
43
|
+
#
|
|
44
|
+
# @example Render a datetime column describing when the record was created
|
|
45
|
+
# <% row.datetime :created_at %> # => <td>29 Feb 2024, 5:00pm</td>
|
|
46
|
+
def datetime(method, format: :admin, **attributes, &block)
|
|
47
|
+
with_column(Body::DatetimeComponent.new(@table, @record, method, format:, **attributes), &block)
|
|
17
48
|
end
|
|
18
49
|
|
|
19
|
-
|
|
20
|
-
|
|
50
|
+
# Generates a column from numeric values formatted appropriately.
|
|
51
|
+
#
|
|
52
|
+
# @param method [Symbol] the method to call on the record
|
|
53
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
54
|
+
# @param block [Proc] optional block to alter the cell content
|
|
55
|
+
# @return [void]
|
|
56
|
+
#
|
|
57
|
+
# @example Render the number of comments on a post
|
|
58
|
+
# <% row.number :comment_count %> # => <td>0</td>
|
|
59
|
+
def number(method, **attributes, &block)
|
|
60
|
+
with_column(Body::NumberComponent.new(@table, @record, method, **attributes), &block)
|
|
21
61
|
end
|
|
22
62
|
|
|
23
|
-
|
|
24
|
-
|
|
63
|
+
# Generates a column from numeric values rendered using `number_to_currency`.
|
|
64
|
+
#
|
|
65
|
+
# @param method [Symbol] the method to call on the record
|
|
66
|
+
# @param options [Hash] options to be passed to `number_to_currency`
|
|
67
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
68
|
+
# @param block [Proc] optional block to alter the cell content
|
|
69
|
+
# @return [void]
|
|
70
|
+
#
|
|
71
|
+
# @example Render a currency column for the price of a product
|
|
72
|
+
# <% row.currency :price %> # => <td>$3.50</td>
|
|
73
|
+
def currency(method, options: {}, **attributes, &block)
|
|
74
|
+
with_column(Body::CurrencyComponent.new(@table, @record, method, options:, **attributes), &block)
|
|
25
75
|
end
|
|
26
76
|
|
|
27
|
-
|
|
28
|
-
|
|
77
|
+
# Generates a column containing HTML markup.
|
|
78
|
+
#
|
|
79
|
+
# @param method [Symbol] the method to call on the record
|
|
80
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
81
|
+
# @param block [Proc] optional block to alter the cell content
|
|
82
|
+
# @return [void]
|
|
83
|
+
#
|
|
84
|
+
# @note This method assumes that the method returns HTML-safe content.
|
|
85
|
+
# If the content is not HTML-safe, it will be escaped.
|
|
86
|
+
#
|
|
87
|
+
# @example Render a description column containing HTML markup
|
|
88
|
+
# <% row.rich_text :description %> # => <td><em>Emphasis</em></td>
|
|
89
|
+
def rich_text(method, **attributes, &block)
|
|
90
|
+
with_column(Body::RichTextComponent.new(@table, @record, method, **attributes), &block)
|
|
29
91
|
end
|
|
30
92
|
|
|
31
|
-
|
|
32
|
-
|
|
93
|
+
# Generates a column that links to the record's show page (by default).
|
|
94
|
+
#
|
|
95
|
+
# @param method [Symbol] the method to call on the record
|
|
96
|
+
# @param link [Hash] options to be passed to the link_to helper
|
|
97
|
+
# @option opts [Hash, Array, String, Symbol] :url ([:admin, object]) options for url_for,
|
|
98
|
+
# or a symbol to be passed to the route helper
|
|
99
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
100
|
+
# @param block [Proc] optional block to alter the cell content
|
|
101
|
+
# @return [void]
|
|
102
|
+
#
|
|
103
|
+
# @example Render a column containing the record's title, linked to its show page
|
|
104
|
+
# <% row.link :title %> # => <td><a href="/admin/post/15">About us</a></td>
|
|
105
|
+
# @example Render a column containing the record's title, linked to its edit page
|
|
106
|
+
# <% row.link :title, url: :edit_admin_post_path do |cell| %>
|
|
107
|
+
# Edit <%= cell %>
|
|
108
|
+
# <% end %>
|
|
109
|
+
# # => <td><a href="/admin/post/15/edit">Edit About us</a></td>
|
|
110
|
+
def link(method, url: [:admin, @record], link: {}, **attributes, &block)
|
|
111
|
+
with_column(Body::LinkComponent.new(@table, @record, method, url:, link:, **attributes), &block)
|
|
33
112
|
end
|
|
34
113
|
|
|
35
|
-
|
|
36
|
-
|
|
114
|
+
# Generates a column that renders the contents as text.
|
|
115
|
+
#
|
|
116
|
+
# @param method [Symbol] the method to call on the record
|
|
117
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
118
|
+
# @param block [Proc] optional block to alter the cell content
|
|
119
|
+
# @return [void]
|
|
120
|
+
#
|
|
121
|
+
# @example Render a column containing the record's title
|
|
122
|
+
# <% row.text :title %> # => <td>About us</td>
|
|
123
|
+
def text(method, **attributes, &block)
|
|
124
|
+
with_column(BodyCellComponent.new(@table, @record, method, **attributes), &block)
|
|
37
125
|
end
|
|
38
126
|
|
|
39
|
-
|
|
40
|
-
|
|
127
|
+
# Generates a column that renders an ActiveStorage attachment as a downloadable link.
|
|
128
|
+
#
|
|
129
|
+
# @param method [Symbol] the method to call on the record
|
|
130
|
+
# @param variant [Symbol] the variant to use when rendering the image (default :thumb)
|
|
131
|
+
# @param attributes [Hash] HTML attributes to be added to the cell tag
|
|
132
|
+
# @param block [Proc] optional block to alter the cell content
|
|
133
|
+
# @return [void]
|
|
134
|
+
#
|
|
135
|
+
# @example Render a column containing a download link to the record's background image
|
|
136
|
+
# <% row.attachment :background %> # => <td><a href="...">background.png</a></td>
|
|
137
|
+
def attachment(method, variant: :thumb, **attributes, &block)
|
|
138
|
+
with_column(Body::AttachmentComponent.new(@table, @record, method, variant:, **attributes), &block)
|
|
41
139
|
end
|
|
42
140
|
end
|
|
43
141
|
end
|
|
@@ -1,11 +1,61 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
|
4
|
+
|
|
3
5
|
module Koi
|
|
4
6
|
module Tables
|
|
5
7
|
module Header
|
|
6
8
|
class NumberComponent < HeaderCellComponent
|
|
7
9
|
def default_html_attributes
|
|
8
|
-
|
|
10
|
+
super.merge_html(class: "type-number")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class CurrencyComponent < HeaderCellComponent
|
|
15
|
+
def default_html_attributes
|
|
16
|
+
super.merge_html(class: "type-currency")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class BooleanComponent < HeaderCellComponent
|
|
21
|
+
def default_html_attributes
|
|
22
|
+
super.merge_html(class: "type-boolean")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class DateComponent < HeaderCellComponent
|
|
27
|
+
def default_html_attributes
|
|
28
|
+
super.merge_html(class: "type-date")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class DateTimeComponent < HeaderCellComponent
|
|
33
|
+
def default_html_attributes
|
|
34
|
+
super.merge_html(class: "type-datetime")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class LinkComponent < HeaderCellComponent
|
|
39
|
+
def default_html_attributes
|
|
40
|
+
super.merge_html(class: "type-link")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class TextComponent < HeaderCellComponent
|
|
45
|
+
def default_html_attributes
|
|
46
|
+
super.merge_html(class: "type-text")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class ImageComponent < HeaderCellComponent
|
|
51
|
+
def default_html_attributes
|
|
52
|
+
super.merge_html(class: "type-image")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class AttachmentComponent < HeaderCellComponent
|
|
57
|
+
def default_html_attributes
|
|
58
|
+
super.merge_html(class: "type-attachment")
|
|
9
59
|
end
|
|
10
60
|
end
|
|
11
61
|
end
|
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
|
4
|
+
|
|
3
5
|
module Koi
|
|
4
6
|
module Tables
|
|
5
7
|
class HeaderCellComponent < Katalyst::Tables::HeaderCellComponent
|
|
8
|
+
attr_reader :width
|
|
9
|
+
|
|
10
|
+
def initialize(table, attribute, label: nil, link: {}, width: nil, **html_attributes)
|
|
11
|
+
@width = width
|
|
12
|
+
|
|
13
|
+
super(table, attribute, label:, link:, **html_attributes)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def default_html_attributes
|
|
17
|
+
super.merge_html(class: width_class)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def width_class
|
|
23
|
+
case width
|
|
24
|
+
when :xs
|
|
25
|
+
"width-xs"
|
|
26
|
+
when :s
|
|
27
|
+
"width-s"
|
|
28
|
+
when :m
|
|
29
|
+
"width-m"
|
|
30
|
+
when :l
|
|
31
|
+
"width-l"
|
|
32
|
+
else
|
|
33
|
+
""
|
|
34
|
+
end
|
|
35
|
+
end
|
|
6
36
|
end
|
|
7
37
|
end
|
|
8
38
|
end
|