avo 1.0.5 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +5 -1
- data/Gemfile.lock +11 -3
- data/app/components/avo/index/grid_cover_empty_state_component.html.erb +3 -0
- data/app/components/avo/index/grid_cover_empty_state_component.rb +4 -0
- data/app/components/avo/index/grid_item_component.html.erb +4 -4
- data/app/components/avo/modal_component.rb +2 -1
- data/app/components/avo/panel_component.html.erb +7 -2
- data/app/components/avo/panel_component.rb +4 -1
- data/app/components/avo/show/fields/has_one_field_component.html.erb +3 -3
- data/app/components/avo/views/resource_edit_component.html.erb +3 -3
- data/app/components/avo/views/resource_index_component.html.erb +4 -4
- data/app/components/avo/views/resource_new_component.html.erb +3 -3
- data/app/components/avo/views/resource_show_component.html.erb +2 -2
- data/app/controllers/avo/application_controller.rb +12 -8
- data/app/controllers/avo/base_controller.rb +16 -0
- data/app/controllers/avo/home_controller.rb +2 -0
- data/app/helpers/avo/application_helper.rb +0 -30
- data/app/packs/entrypoints/application.css +1 -0
- data/app/packs/stylesheets/breadcrumbs.css +12 -0
- data/app/packs/svgs/chevron-right.svg +3 -0
- data/app/views/avo/actions/show.html.erb +2 -2
- data/app/views/avo/home/_actions.html.erb +5 -5
- data/app/views/avo/home/_docs.html.erb +1 -1
- data/app/views/avo/home/_filters.html.erb +4 -4
- data/app/views/avo/home/_resources.html.erb +15 -2
- data/app/views/avo/home/index.html.erb +4 -4
- data/{lib/generators/avo/templates → app/views/avo}/partials/_scripts.html.erb +0 -0
- data/app/views/avo/relations/new.html.erb +2 -2
- data/app/views/avo/sidebar/_sidebar.html.erb +12 -3
- data/app/views/layouts/avo/application.html.erb +5 -4
- data/avo.gemspec +2 -0
- data/lib/avo/app.rb +33 -10
- data/lib/avo/base_resource.rb +1 -0
- data/lib/avo/configuration.rb +11 -1
- data/lib/avo/grid_collector.rb +1 -1
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/eject_generator.rb +55 -0
- data/lib/generators/avo/templates/tool/controller.tt +2 -0
- data/lib/generators/avo/templates/tool/sidebar_item.tt +1 -0
- data/lib/generators/avo/templates/tool/view.tt +27 -0
- data/lib/generators/avo/tool_generator.rb +62 -0
- data/public/avo-packs/css/{application-9d115b7e.css → application-43cdc2a7.css} +44 -7
- data/public/avo-packs/css/application-43cdc2a7.css.br +0 -0
- data/public/avo-packs/css/application-43cdc2a7.css.gz +0 -0
- data/public/avo-packs/css/application-43cdc2a7.css.map +1 -0
- data/public/avo-packs/css/application-43cdc2a7.css.map.br +0 -0
- data/public/avo-packs/css/application-43cdc2a7.css.map.gz +0 -0
- data/public/avo-packs/manifest.json +7 -7
- metadata +46 -13
- data/lib/generators/avo/partials_generator.rb +0 -14
- data/lib/generators/avo/templates/partials/_footer.html.erb +0 -3
- data/lib/generators/avo/templates/partials/_header.html.erb +0 -1
- data/lib/generators/avo/templates/partials/_logo.html.erb +0 -1
- data/public/avo-packs/css/application-9d115b7e.css.br +0 -0
- data/public/avo-packs/css/application-9d115b7e.css.gz +0 -0
- data/public/avo-packs/css/application-9d115b7e.css.map +0 -1
- data/public/avo-packs/css/application-9d115b7e.css.map.br +0 -0
- data/public/avo-packs/css/application-9d115b7e.css.map.gz +0 -0
@@ -9,7 +9,7 @@
|
|
9
9
|
>
|
10
10
|
<%= form_with model: @model, scope: 'fields', url: "/avo/resources/#{@resource.model_class.model_name.route_key}/actions/#{@action.param_id}", data: {'turbo-frame': '_top', 'action-target': 'form'} do |form| %>
|
11
11
|
<%= render Avo::ModalComponent.new do |c| %>
|
12
|
-
<% c.
|
12
|
+
<% c.heading do %>
|
13
13
|
<%= @action.name %>
|
14
14
|
<% end %>
|
15
15
|
|
@@ -25,7 +25,7 @@
|
|
25
25
|
<% end %>
|
26
26
|
<% end %>
|
27
27
|
|
28
|
-
<% c.
|
28
|
+
<% c.controls do %>
|
29
29
|
<%= a_button @action.cancel_button_label, 'data-action': 'click->modal#close', size: :sm %>
|
30
30
|
<%= a_button @action.confirm_button_label, type: :submit, color: :green, size: :sm %>
|
31
31
|
<% end %>
|
@@ -1,16 +1,16 @@
|
|
1
1
|
<div>
|
2
2
|
<h3>Actions</h3>
|
3
3
|
|
4
|
-
<div class="mt-2"
|
4
|
+
<div class="mt-2">
|
5
5
|
Avo actions allow you to perform specific tasks on one or more of your records. For example, you might want to mark a user as inactive and optionally send a message that may be customized by the person that wants to run the action.
|
6
6
|
|
7
|
-
<
|
8
|
-
|
9
|
-
<div class="mt-2 hidden" data-hidden-input-target="content">
|
7
|
+
<div class="mt-2">
|
10
8
|
<code class="text-lg">Toggle published</code>
|
11
|
-
<div>
|
9
|
+
<div class="mt-1">
|
12
10
|
<code class="p-1 rounded bg-light-blue-500 text-white">bin/rails generate avo:action toggle_published</code>
|
13
11
|
</div>
|
14
12
|
</div>
|
13
|
+
|
14
|
+
<a href="https://docs.avohq.io/1.0/actions.html" target="_blank" title="Avo Actions documentation" class="text-bold cursor-pointer block mt-2">Actions in the docs 👉</a>
|
15
15
|
</div>
|
16
16
|
</div>
|
@@ -4,6 +4,6 @@
|
|
4
4
|
<div class="mt-2">
|
5
5
|
We take pride in our documentation. Please check it out to see what you can build with Avo
|
6
6
|
|
7
|
-
<a href="https://docs.avohq.io" class="text-bold cursor-pointer block mt-2">Check out the docs 👉</a>
|
7
|
+
<a href="https://docs.avohq.io" target="_blank" title="Avo documentation" class="text-bold cursor-pointer block mt-2">Check out the docs 👉</a>
|
8
8
|
</div>
|
9
9
|
</div>
|
@@ -4,13 +4,13 @@
|
|
4
4
|
<div class="mt-2" data-controller="hidden-input">
|
5
5
|
Filters allow you to better scope the index queries for records you are looking for.
|
6
6
|
|
7
|
-
<
|
8
|
-
|
9
|
-
<div class="mt-2 hidden" data-hidden-input-target="content">
|
7
|
+
<div class="mt-2">
|
10
8
|
<code class="text-lg">Published filter</code>
|
11
|
-
<div>
|
9
|
+
<div class="mt-1">
|
12
10
|
<code class="p-1 rounded bg-light-blue-500 text-white">bin/rails generate avo:filter published_filter</code>
|
13
11
|
</div>
|
14
12
|
</div>
|
13
|
+
|
14
|
+
<a href="https://docs.avohq.io/1.0/filters.html" target="_blank" title="Avo Filters documentation" class="text-bold cursor-pointer block mt-2">Filters in the docs 👉</a>
|
15
15
|
</div>
|
16
16
|
</div>
|
@@ -1,5 +1,9 @@
|
|
1
1
|
<%
|
2
|
-
models =
|
2
|
+
models = begin
|
3
|
+
ApplicationRecord.descendants
|
4
|
+
rescue => exception
|
5
|
+
[]
|
6
|
+
end
|
3
7
|
%>
|
4
8
|
<div>
|
5
9
|
<h3>Resources</h3>
|
@@ -10,7 +14,7 @@
|
|
10
14
|
<div class="mt-2" data-controller="hidden-input">
|
11
15
|
It seems you already have <%= models.count %> <%= 'model'.pluralize models.count %> in your app. You can generate resources for each one with the following commands.
|
12
16
|
|
13
|
-
<strong class="cursor-pointer block mt-2" data-action="click->hidden-input#showContent">Generate resources
|
17
|
+
<strong class="cursor-pointer block mt-2" data-action="click->hidden-input#showContent">Generate resources 👇 (click to reveal)</strong>
|
14
18
|
|
15
19
|
<div class="mt-2 hidden" data-hidden-input-target="content">
|
16
20
|
<% models.each do |model| %>
|
@@ -22,7 +26,16 @@
|
|
22
26
|
</div>
|
23
27
|
</div>
|
24
28
|
<% else %>
|
29
|
+
<div class="mt-2" data-controller="hidden-input">
|
30
|
+
You may generate a resource using the following command:
|
31
|
+
<br>
|
25
32
|
|
33
|
+
<code class="p-1 rounded bg-light-blue-500 text-white">bin/rails generate avo:resource post</code>
|
34
|
+
</div>
|
26
35
|
<% end %>
|
36
|
+
|
37
|
+
<p>
|
38
|
+
<a href="https://docs.avohq.io/1.0/resources.html" target="_blank" title="Avo Resources documentation">Docs</a>
|
39
|
+
</p>
|
27
40
|
</div>
|
28
41
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
|
-
<%=
|
3
|
-
<% c.
|
2
|
+
<%= render Avo::PanelComponent.new title: 'Welcome to Avo' do |c| %>
|
3
|
+
<% c.tools do %>
|
4
4
|
<div class="text-sm italic">This page is visible only in development. It will be hidden in other environments.</div>
|
5
5
|
<% end %>
|
6
6
|
|
7
|
-
<% c.
|
7
|
+
<% c.body do %>
|
8
8
|
<div class="flex flex-col justify-between py-6 min-h-24">
|
9
9
|
<div class="px-6 space-y-4">
|
10
10
|
<h3>About</h3>
|
@@ -27,7 +27,7 @@
|
|
27
27
|
<li><span class="mr-2">👍</span> Grid view</li>
|
28
28
|
<li><span class="mr-2">👍</span> Authorization</li>
|
29
29
|
<li><span class="mr-2">👍</span> Localization</li>
|
30
|
-
<li><span class="mr-2"
|
30
|
+
<li><span class="mr-2">👍</span> Custom tools</li>
|
31
31
|
<li><span class="mr-2">⏳</span> Custom fields</li>
|
32
32
|
<li><span class="mr-2">⏳</span> Search</li>
|
33
33
|
<li><span class="mr-2">🕐</span> Dashboards</li>
|
File without changes
|
@@ -5,7 +5,7 @@
|
|
5
5
|
'turbo-frame': '_top'
|
6
6
|
} do |form| %>
|
7
7
|
<%= render Avo::ModalComponent.new do |c| %>
|
8
|
-
<% c.
|
8
|
+
<% c.heading do %>
|
9
9
|
<%= t 'avo.choose_item', item: params[:related_name].downcase %>
|
10
10
|
<% end %>
|
11
11
|
|
@@ -24,7 +24,7 @@
|
|
24
24
|
|
25
25
|
<%#= form.hidden_field :resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
|
26
26
|
|
27
|
-
<% c.
|
27
|
+
<% c.controls do %>
|
28
28
|
<%= a_button t('avo.cancel'), 'data-action': 'click->modal#close', size: :sm %>
|
29
29
|
<%= a_button t('avo.attach'), type: :submit, color: :green, size: :sm %>
|
30
30
|
<% end %>
|
@@ -1,18 +1,27 @@
|
|
1
1
|
<div class="application-sidebar flex h-full bg-white text-white w-56 z-50 border-r border-gray-300">
|
2
2
|
<div class="flex flex-col w-full">
|
3
3
|
<%= link_to root_path, class: 'logo-placeholder h-16 bg-white p-2 flex justify-center' do %>
|
4
|
-
<%=
|
4
|
+
<%= render partial: "avo/partials/logo" %>
|
5
5
|
<% end %>
|
6
6
|
|
7
7
|
<div class="flex-1 flex flex-col justify-between">
|
8
8
|
<div class="tools py-4">
|
9
|
-
<%= render Avo::NavigationLinkComponent.new label: 'Get started', path:
|
9
|
+
<%= render Avo::NavigationLinkComponent.new label: 'Get started', path: Avo.configuration.root_path, active: :exclusive if Rails.env.development? %>
|
10
10
|
<%= render Avo::NavigationHeadingComponent.new label: t('avo.resources') %>
|
11
11
|
|
12
12
|
<div class="w-full">
|
13
|
-
<% Avo::App.
|
13
|
+
<% Avo::App.resources_navigation(_current_user).each do |resource| %>
|
14
14
|
<%= render Avo::NavigationLinkComponent.new label: resource.name.pluralize.humanize, path: resources_path(resource.model_class) %>
|
15
15
|
<% end %>
|
16
|
+
|
17
|
+
<% sidebar_partials = Avo::App.get_sidebar_partials %>
|
18
|
+
<% if sidebar_partials.present? %>
|
19
|
+
<%= render Avo::NavigationHeadingComponent.new label: t('avo.tools') %>
|
20
|
+
|
21
|
+
<% sidebar_partials.each do |partial| %>
|
22
|
+
<%= render partial: "/avo/sidebar/items/#{partial}" %>
|
23
|
+
<% end %>
|
24
|
+
<% end %>
|
16
25
|
</div>
|
17
26
|
|
18
27
|
</div>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
|
4
|
+
<%= display_meta_tags site: Avo.configuration.app_name, reverse: true, separator: "—" %>
|
5
5
|
|
6
6
|
<%= csrf_meta_tags %>
|
7
7
|
<%= csp_meta_tag %>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
<div class="flex-1 flex flex-col h-full overflow-auto">
|
21
21
|
<div class="relative bg-white p-2 shadow-md h-16 w-full flex flex-shrink-0 items-center z-50" v-if="layout !== 'blank'">
|
22
22
|
<div class="ml-6">
|
23
|
-
<%=
|
23
|
+
<%= render partial: "avo/partials/header" %>
|
24
24
|
</div>
|
25
25
|
<div class="flex-1 flex justify-center">
|
26
26
|
<div class="w-64">
|
@@ -31,7 +31,7 @@
|
|
31
31
|
|
32
32
|
<div class="content p-8 flex-1 flex flex-col justify-between items-stretch <%= @container_classes %>">
|
33
33
|
<%= yield %>
|
34
|
-
<%=
|
34
|
+
<%= render partial: "avo/partials/footer" %>
|
35
35
|
</div>
|
36
36
|
</div>
|
37
37
|
</div>
|
@@ -44,6 +44,7 @@
|
|
44
44
|
<% end %>
|
45
45
|
</div>
|
46
46
|
|
47
|
-
<%=
|
47
|
+
<%= render partial: "avo/partials/scripts" %>
|
48
|
+
<!-- Avo version: <%= Avo::VERSION %> -->
|
48
49
|
</body>
|
49
50
|
</html>
|
data/avo.gemspec
CHANGED
data/lib/avo/app.rb
CHANGED
@@ -27,7 +27,11 @@ module Avo
|
|
27
27
|
self.context = context
|
28
28
|
|
29
29
|
# Set the current host for ActiveStorage
|
30
|
-
|
30
|
+
begin
|
31
|
+
ActiveStorage::Current.host = request.base_url
|
32
|
+
rescue => exception
|
33
|
+
Rails.logger.debug "[Avo] Failed to set ActiveStorage::Current.host, #{exception.inspect}"
|
34
|
+
end
|
31
35
|
|
32
36
|
init_resources
|
33
37
|
|
@@ -129,10 +133,28 @@ module Avo
|
|
129
133
|
.sort_by { |r| r.name }
|
130
134
|
end
|
131
135
|
|
132
|
-
def
|
136
|
+
def resources_navigation(user = nil)
|
133
137
|
get_available_resources(user).select do |resource|
|
134
138
|
resource.model_class.present?
|
135
139
|
end
|
140
|
+
.select do |resource|
|
141
|
+
resource.visible_on_sidebar
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Insert any partials that we find in app/views/avo/sidebar/items.
|
146
|
+
def get_sidebar_partials
|
147
|
+
Dir.glob(Rails.root.join("app", "views", "avo", "sidebar", "items", "*.html.erb"))
|
148
|
+
.map do |path|
|
149
|
+
File.basename path
|
150
|
+
end
|
151
|
+
.map do |filename|
|
152
|
+
# remove the leading underscore (_)
|
153
|
+
filename[0] = ""
|
154
|
+
# remove the extension
|
155
|
+
filename.gsub!('.html.erb', '')
|
156
|
+
filename
|
157
|
+
end
|
136
158
|
end
|
137
159
|
|
138
160
|
def draw_routes
|
@@ -144,16 +166,17 @@ module Avo
|
|
144
166
|
.select do |resource|
|
145
167
|
resource != :BaseResource
|
146
168
|
end
|
169
|
+
.select do |resource|
|
170
|
+
resource.is_a? Class
|
171
|
+
end
|
147
172
|
.map do |resource|
|
148
|
-
if resource.
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
resource.to_s.underscore.gsub("_resource", "").downcase.pluralize.to_sym
|
153
|
-
end
|
154
|
-
|
155
|
-
resources route_key
|
173
|
+
route_key = if resource.model_class.present?
|
174
|
+
resource.model_class.model_name.route_key
|
175
|
+
else
|
176
|
+
resource.to_s.underscore.gsub("_resource", "").downcase.pluralize.to_sym
|
156
177
|
end
|
178
|
+
|
179
|
+
resources route_key
|
157
180
|
end
|
158
181
|
end
|
159
182
|
end
|
data/lib/avo/base_resource.rb
CHANGED
data/lib/avo/configuration.rb
CHANGED
@@ -19,10 +19,12 @@ module Avo
|
|
19
19
|
attr_accessor :full_width_index_view
|
20
20
|
attr_accessor :cache_resources_on_index_view
|
21
21
|
attr_accessor :context
|
22
|
+
attr_accessor :display_breadcrumbs
|
23
|
+
attr_accessor :initial_breadcrumbs
|
22
24
|
|
23
25
|
def initialize
|
24
26
|
@root_path = "/avo"
|
25
|
-
@app_name = Rails.application.class.to_s.split("::").first.underscore.humanize(keep_id_suffix: true)
|
27
|
+
@app_name = ::Rails.application.class.to_s.split("::").first.underscore.humanize(keep_id_suffix: true)
|
26
28
|
@timezone = "UTC"
|
27
29
|
@per_page = 24
|
28
30
|
@per_page_steps = [12, 24, 48, 72]
|
@@ -48,6 +50,10 @@ module Avo
|
|
48
50
|
@full_width_index_view = false
|
49
51
|
@cache_resources_on_index_view = Avo::PACKED
|
50
52
|
@context = proc {}
|
53
|
+
@initial_breadcrumbs = proc {
|
54
|
+
add_breadcrumb I18n.t("avo.home").humanize, avo.root_path
|
55
|
+
}
|
56
|
+
@display_breadcrumbs = true
|
51
57
|
end
|
52
58
|
|
53
59
|
def locale_tag
|
@@ -71,6 +77,10 @@ module Avo
|
|
71
77
|
def set_context(&block)
|
72
78
|
@context = block if block.present?
|
73
79
|
end
|
80
|
+
|
81
|
+
def set_initial_breadcrumbs(&block)
|
82
|
+
@initial_breadcrumbs = block if block.present?
|
83
|
+
end
|
74
84
|
end
|
75
85
|
|
76
86
|
def self.configuration
|
data/lib/avo/grid_collector.rb
CHANGED
@@ -27,7 +27,7 @@ module Avo
|
|
27
27
|
def hydrate(model:, view:, resource:)
|
28
28
|
cover_field.hydrate(model: model, view: view, resource: resource) if cover_field.present?
|
29
29
|
title_field.hydrate(model: model, view: view, resource: resource) if title_field.present?
|
30
|
-
body_field.hydrate(model: model, view: view, resource: resource) if
|
30
|
+
body_field.hydrate(model: model, view: view, resource: resource) if body_field.present?
|
31
31
|
|
32
32
|
self
|
33
33
|
end
|
data/lib/avo/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
module Generators
|
5
|
+
module Avo
|
6
|
+
class EjectGenerator < ::Rails::Generators::Base
|
7
|
+
argument :filename, type: :string, required: true
|
8
|
+
|
9
|
+
source_root ::Avo::Engine.root
|
10
|
+
|
11
|
+
namespace "avo:eject"
|
12
|
+
|
13
|
+
TEMPLATES = {
|
14
|
+
sidebar: "app/views/avo/sidebar/_sidebar.html.erb",
|
15
|
+
logo: "app/views/avo/partials/logo.html.erb",
|
16
|
+
header: "app/views/avo/partials/header.html.erb",
|
17
|
+
footer: "app/views/avo/partials/footer.html.erb",
|
18
|
+
scripts: "app/views/avo/partials/scripts.html.erb"
|
19
|
+
}
|
20
|
+
|
21
|
+
def handle
|
22
|
+
if @filename.starts_with?(":")
|
23
|
+
template_id = path_to_sym @filename
|
24
|
+
template_path = TEMPLATES[template_id]
|
25
|
+
|
26
|
+
if path_exists? template_path
|
27
|
+
eject template_path
|
28
|
+
else
|
29
|
+
say("Failed to find the `#{template_id.to_sym}` template.", :yellow)
|
30
|
+
end
|
31
|
+
elsif path_exists? @filename
|
32
|
+
eject @filename
|
33
|
+
else
|
34
|
+
say("Failed to find the `#{@filename}` template.", :yellow)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
no_tasks do
|
39
|
+
def path_to_sym(filename)
|
40
|
+
template_id = filename.dup
|
41
|
+
template_id[0] = ""
|
42
|
+
template_id.to_sym
|
43
|
+
end
|
44
|
+
|
45
|
+
def path_exists?(path)
|
46
|
+
path.present? && File.file?(::Avo::Engine.root.join(path))
|
47
|
+
end
|
48
|
+
|
49
|
+
def eject(path)
|
50
|
+
copy_file ::Avo::Engine.root.join(path), ::Rails.root.join(path)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%%= render Avo::NavigationLinkComponent.new label: '<%= human_name %>', path: '/avo/<%= file_name %>' %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div class="flex flex-col">
|
2
|
+
<%%= render Avo::PanelComponent.new title: '<%= human_name %>' do |c| %>
|
3
|
+
<%% c.tools do %>
|
4
|
+
<div class="text-sm italic">This is the panels tools section.</div>
|
5
|
+
<%% end %>
|
6
|
+
|
7
|
+
<%% c.body do %>
|
8
|
+
<div class="flex flex-col justify-between py-6 min-h-24">
|
9
|
+
<div class="px-6 space-y-4">
|
10
|
+
<h3>What a nice new tool 👋</h3>
|
11
|
+
|
12
|
+
<p>
|
13
|
+
You can edit this file here <%= in_code "app/views/avo/tools/#{file_name}.html.erb" %>.
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<p>
|
17
|
+
For this tool we created the <%= in_code file_name %> method in the <%= in_code "Avo::ToolsController" %>. You may delete it or move it to your own controller.
|
18
|
+
</p>
|
19
|
+
|
20
|
+
<p>
|
21
|
+
A new <%= in_code human_name %> item should have been added to the sidebar. Edit it in <%= in_code "app/views/avo/sidebar/items/_#{file_name}.html.erb" %>
|
22
|
+
</p>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
<%% end %>
|
26
|
+
<%% end %>
|
27
|
+
</div>
|