avo 1.1.0 → 1.2.6.pre.1
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 +10 -2
- 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 +20 -0
- data/app/controllers/avo/base_controller.rb +16 -0
- data/app/controllers/avo/home_controller.rb +5 -1
- data/app/helpers/avo/application_helper.rb +0 -6
- data/app/packs/entrypoints/application.css +1 -0
- data/app/packs/stylesheets/breadcrumbs.css +12 -0
- data/app/packs/stylesheets/components/code.css +5 -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/app/views/avo/relations/new.html.erb +2 -2
- data/app/views/avo/sidebar/_sidebar.html.erb +2 -1
- data/app/views/layouts/avo/application.html.erb +3 -2
- data/avo.gemspec +2 -0
- data/lib/avo.rb +4 -0
- data/lib/avo/app.rb +21 -11
- data/lib/avo/base_resource.rb +1 -0
- data/lib/avo/configuration.rb +17 -1
- data/lib/avo/grid_collector.rb +1 -1
- data/lib/avo/licensing/h_q.rb +3 -3
- data/lib/avo/licensing/license.rb +2 -0
- data/lib/avo/licensing/pro_license.rb +2 -1
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/templates/initializer/avo.tt +10 -1
- data/lib/generators/avo/templates/tool/view.tt +3 -3
- data/lib/generators/avo/tool_generator.rb +5 -3
- data/public/avo-packs/css/{application-9d115b7e.css → application-b5f285ce.css} +49 -7
- data/public/avo-packs/css/application-b5f285ce.css.br +0 -0
- data/public/avo-packs/css/application-b5f285ce.css.gz +0 -0
- data/public/avo-packs/css/application-b5f285ce.css.map +1 -0
- data/public/avo-packs/css/application-b5f285ce.css.map.br +0 -0
- data/public/avo-packs/css/application-b5f285ce.css.map.gz +0 -0
- data/public/avo-packs/js/application-e351ef988a3cb9687542.js.map +1 -1
- data/public/avo-packs/js/application-e351ef988a3cb9687542.js.map.br +0 -0
- data/public/avo-packs/js/application-e351ef988a3cb9687542.js.map.gz +0 -0
- data/public/avo-packs/manifest.json +7 -7
- metadata +42 -10
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14e502a4a38c39f136298b688cb7df3be49612444de569c358aff07828c5ab7d
|
4
|
+
data.tar.gz: cf7bdebe1e32e73021c1b78a7200887b26e766471300ff6645c62353c9b9f1fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 412610059431101fdebbcadeee2618941aa072ace0305937918ff78127409288e23109f4a3d4653d4a7a6495aa25a78066dc5f8e37ca1654bfe53aa5abed086a
|
7
|
+
data.tar.gz: 943c91cf7c347952a8b7c9da989b23d8ed45d6362547e2bc23524a0725008f87fc8f23ab9ad31f380564efd61fd5aee30b8c864def7eb9998a217e4f1bb81c01
|
data/Gemfile
CHANGED
@@ -52,7 +52,7 @@ gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
|
|
52
52
|
gem "dotenv-rails"
|
53
53
|
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
|
54
54
|
gem "web-console", ">= 3.3.0"
|
55
|
-
gem "listen", ">= 3.
|
55
|
+
gem "listen", ">= 3.5.1"
|
56
56
|
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
57
57
|
gem "spring"
|
58
58
|
|
@@ -119,3 +119,7 @@ gem "view_component", require: "view_component/engine"
|
|
119
119
|
gem "addressable"
|
120
120
|
|
121
121
|
gem "appraisal"
|
122
|
+
|
123
|
+
gem 'meta-tags'
|
124
|
+
|
125
|
+
gem 'breadcrumbs_on_rails'
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.1
|
4
|
+
avo (1.2.6.pre.1)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
|
+
breadcrumbs_on_rails
|
7
8
|
countries
|
8
9
|
hotwire-rails
|
9
10
|
httparty
|
10
11
|
image_processing
|
12
|
+
meta-tags
|
11
13
|
pagy
|
12
14
|
pundit
|
13
15
|
rails (>= 6.0)
|
@@ -87,6 +89,8 @@ GEM
|
|
87
89
|
bindex (0.8.1)
|
88
90
|
bootsnap (1.4.8)
|
89
91
|
msgpack (~> 1.0)
|
92
|
+
breadcrumbs_on_rails (4.0.0)
|
93
|
+
rails (>= 5.0)
|
90
94
|
builder (3.2.4)
|
91
95
|
bump (0.9.0)
|
92
96
|
byebug (11.1.3)
|
@@ -161,6 +165,8 @@ GEM
|
|
161
165
|
mail (2.7.1)
|
162
166
|
mini_mime (>= 0.1.1)
|
163
167
|
marcel (1.0.0)
|
168
|
+
meta-tags (2.14.0)
|
169
|
+
actionpack (>= 3.2.0, < 6.2)
|
164
170
|
method_source (1.0.0)
|
165
171
|
mime-types (3.3.1)
|
166
172
|
mime-types-data (~> 3.2015)
|
@@ -356,6 +362,7 @@ DEPENDENCIES
|
|
356
362
|
appraisal
|
357
363
|
avo!
|
358
364
|
bootsnap (>= 1.4.2)
|
365
|
+
breadcrumbs_on_rails
|
359
366
|
bump
|
360
367
|
byebug
|
361
368
|
capybara (>= 2.15)
|
@@ -372,7 +379,8 @@ DEPENDENCIES
|
|
372
379
|
image_processing (~> 1.2)
|
373
380
|
iso
|
374
381
|
jbuilder (~> 2.7)
|
375
|
-
listen (>= 3.
|
382
|
+
listen (>= 3.5.1)
|
383
|
+
meta-tags
|
376
384
|
pg (>= 0.18, < 2.0)
|
377
385
|
puma (~> 4.3.5)
|
378
386
|
pundit
|
@@ -4,7 +4,9 @@
|
|
4
4
|
<div class="relative w-full pb-3/4 rounded-t-xl overflow-hidden">
|
5
5
|
<%== item_selector_input floating: true, size: :lg %>
|
6
6
|
|
7
|
-
<% if cover.
|
7
|
+
<% if cover.blank? %>
|
8
|
+
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
9
|
+
<% elsif cover.respond_to? :to_image %>
|
8
10
|
<%= link_to_if cover.link_to_resource, image_tag(cover.to_image, class: 'absolute h-full w-full object-cover'), helpers.resource_path(@resource.model), class: 'absolute h-full w-full object-cover', title: title.value %>
|
9
11
|
<% elsif cover.type == 'file' %>
|
10
12
|
<% if cover.value.attached? && cover.value.representable? %>
|
@@ -18,9 +20,7 @@
|
|
18
20
|
<% if cover.value.present? %>
|
19
21
|
<%= link_to_if cover.link_to_resource, image_tag(cover.value, class: 'absolute h-full w-full object-cover'), helpers.resource_path(@resource.model), class: 'absolute h-full w-full object-cover', title: title.value %>
|
20
22
|
<% else %>
|
21
|
-
|
22
|
-
<%= helpers.svg 'avocado', class: 'relative transform -translate-x-1/2 -translate-y-1/2 h-20 text-gray-400 inset-auto top-1/2 left-1/2' %>
|
23
|
-
</div>
|
23
|
+
<%= render Avo::Index::GridCoverEmptyStateComponent.new %>
|
24
24
|
<% end %>
|
25
25
|
<% end %>
|
26
26
|
</div>
|
@@ -1,7 +1,12 @@
|
|
1
1
|
<div <%== data_attributes %>>
|
2
2
|
<div class="mb-6">
|
3
|
-
<div
|
4
|
-
|
3
|
+
<div>
|
4
|
+
<div class="breadcrumbs">
|
5
|
+
<%= helpers.render_breadcrumbs(separator: helpers.svg('chevron-right', class: 'inline-block h-3 stroke-current relative top-[-1px] ml-1' )) if Avo.configuration.display_breadcrumbs %>
|
6
|
+
</div>
|
7
|
+
<div class="text-2xl tracking-normal font-bold text-gray-800 truncate">
|
8
|
+
<%= @title %>
|
9
|
+
</div>
|
5
10
|
</div>
|
6
11
|
|
7
12
|
<div>
|
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Avo::PanelComponent < ViewComponent::Base
|
4
|
-
|
4
|
+
renders_one :tools
|
5
|
+
renders_one :body
|
6
|
+
renders_one :bare_content
|
7
|
+
renders_one :footer
|
5
8
|
|
6
9
|
def initialize(title: nil, body_classes: nil, data: {})
|
7
10
|
@title = title
|
@@ -3,14 +3,14 @@
|
|
3
3
|
<%= render(Avo::LoadingComponent.new(title: @field.name)) %>
|
4
4
|
</turbo-frame>
|
5
5
|
<% else %>
|
6
|
-
<%=
|
7
|
-
<% c.
|
6
|
+
<%= render Avo::PanelComponent.new(title: @field.id.capitalize) do |c| %>
|
7
|
+
<% c.tools do %>
|
8
8
|
<%= a_link helpers.resource_attach_path(@resource.model.model_name.route_key, @resource.model.id, @field.id), color: 'indigo', 'data-turbo-frame': 'attach_modal' do %>
|
9
9
|
<%= svg 'view-grid-add' %> <%= t('avo.attach_item', item: @field.id).capitalize %>
|
10
10
|
<% end %>
|
11
11
|
<% end %>
|
12
12
|
|
13
|
-
<% c.
|
13
|
+
<% c.body do %>
|
14
14
|
<div class="py-8 flex justify-center items-center">
|
15
15
|
<%= empty_state @field.id %>
|
16
16
|
</div>
|
@@ -3,8 +3,8 @@
|
|
3
3
|
<%= form_with model: @resource.model, url: helpers.resource_path(@resource.model), method: :put, multipart: true do |form| %>
|
4
4
|
<%= hidden_field_tag :referrer, back_path if params[:via_resource_class] %>
|
5
5
|
|
6
|
-
<%=
|
7
|
-
<%
|
6
|
+
<%= render Avo::PanelComponent.new(title: resource_panel[:name]) do |c| %>
|
7
|
+
<% c.tools do %>
|
8
8
|
<div class="flex justify-end space-x-2">
|
9
9
|
<%= a_link back_path do %>
|
10
10
|
<%= helpers.svg 'arrow-left' %> <%= t('avo.cancel').capitalize %>
|
@@ -18,7 +18,7 @@
|
|
18
18
|
</div>
|
19
19
|
<% end %>
|
20
20
|
|
21
|
-
<%
|
21
|
+
<% c.body do %>
|
22
22
|
<% @resource.get_fields.each_with_index do |field, index| %>
|
23
23
|
<%= edit_field field, index, @resource, form unless field.computed %>
|
24
24
|
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<%=
|
2
|
-
<% c.
|
1
|
+
<%= render Avo::PanelComponent.new title: title, body_classes: 'py-4', data: { component: 'resources-index' } do |c| %>
|
2
|
+
<% c.tools do %>
|
3
3
|
<%= render 'actions' if @actions.present? %>
|
4
4
|
|
5
5
|
<% if can_create? %>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<% end %>
|
22
22
|
<% end %>
|
23
23
|
|
24
|
-
<% c.
|
24
|
+
<% c.body do %>
|
25
25
|
<div class="flex justify-between py-6 min-h-24"
|
26
26
|
data-selected-resources-name="<%= @resource.plural_name.downcase %>"
|
27
27
|
data-selected-resources="[]"
|
@@ -51,7 +51,7 @@
|
|
51
51
|
<% end %>
|
52
52
|
|
53
53
|
<% if view_type.to_sym == :grid %>
|
54
|
-
<% c.
|
54
|
+
<% c.bare_content do %>
|
55
55
|
<%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
|
56
56
|
|
57
57
|
<div class="bg-white rounded-xl shadow-xl mt-8 py-6">
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<div>
|
2
2
|
<% @resource.panels.each do |resource_panel| %>
|
3
3
|
<%= form_with model: @resource.model, url: helpers.resources_path(@resource.model, via_relation_class: params[:via_relation_class], via_resource_id: params[:via_resource_id]), local: true, multipart: true do |form| %>
|
4
|
-
<%=
|
5
|
-
<%
|
4
|
+
<%= render Avo::PanelComponent.new(title: resource_panel[:name]) do |c| %>
|
5
|
+
<% c.tools do %>
|
6
6
|
<div class="flex justify-end space-x-2">
|
7
7
|
<%= a_link back_path do %>
|
8
8
|
<%= svg 'arrow-left' %> <%= t('avo.cancel').capitalize %>
|
@@ -14,7 +14,7 @@
|
|
14
14
|
</div>
|
15
15
|
<% end %>
|
16
16
|
|
17
|
-
<%
|
17
|
+
<% c.body do %>
|
18
18
|
<% @resource.get_fields.each_with_index do |field, index| %>
|
19
19
|
<%= edit_field field, index, @resource, form unless field.computed %>
|
20
20
|
<% end %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
>
|
5
5
|
<% @resource.panels.each do |resource_panel| %>
|
6
6
|
<%= render(Avo::PanelComponent.new(title: resource_panel[:name])) do |c| %>
|
7
|
-
<% c.
|
7
|
+
<% c.tools do %>
|
8
8
|
<% if resource_panel[:name] == @resource.default_panel_name %>
|
9
9
|
<%= render 'actions' %>
|
10
10
|
|
@@ -44,7 +44,7 @@
|
|
44
44
|
<% end %>
|
45
45
|
<% end %>
|
46
46
|
|
47
|
-
<% c.
|
47
|
+
<% c.body do %>
|
48
48
|
<% if fields_by_panel[resource_panel[:name]].present? %>
|
49
49
|
<% fields_by_panel[resource_panel[:name]].each_with_index do |field, index| %>
|
50
50
|
<%= show_field field, index, @resource %>
|
@@ -4,9 +4,11 @@ module Avo
|
|
4
4
|
include Pagy::Backend
|
5
5
|
protect_from_forgery with: :exception
|
6
6
|
before_action :init_app
|
7
|
+
before_action :check_avo_license
|
7
8
|
before_action :set_authorization
|
8
9
|
before_action :_authenticate!
|
9
10
|
before_action :set_container_classes
|
11
|
+
before_action :add_initial_breadcrumbs
|
10
12
|
|
11
13
|
rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
|
12
14
|
rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
|
@@ -33,6 +35,20 @@ module Avo
|
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
38
|
+
def render(*args)
|
39
|
+
raise Avo::LicenseTinkeredError, "License verification mechanism tinkered with." unless method(:check_avo_license).source_location.first.match?(/.*\/app\/controllers\/avo\/application_controller\.rb/)
|
40
|
+
|
41
|
+
super(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_avo_license
|
45
|
+
unless request.original_url.match?(/.*\/avo\/resources\/.*/)
|
46
|
+
if !Rails.env.development? && (@license.invalid? || @license.lacks(:custom_tools))
|
47
|
+
raise Avo::LicenseInvalidError, "Your license is invalid."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
36
52
|
def _current_user
|
37
53
|
instance_eval(&Avo.configuration.current_user)
|
38
54
|
end
|
@@ -240,5 +256,9 @@ module Avo
|
|
240
256
|
|
241
257
|
@container_classes = contain ? "2xl:container 2xl:mx-auto" : ""
|
242
258
|
end
|
259
|
+
|
260
|
+
def add_initial_breadcrumbs
|
261
|
+
instance_eval(&Avo.configuration.initial_breadcrumbs) if Avo.configuration.initial_breadcrumbs.present?
|
262
|
+
end
|
243
263
|
end
|
244
264
|
end
|
@@ -9,6 +9,9 @@ module Avo
|
|
9
9
|
before_action :set_model, only: [:show, :edit, :destroy, :update]
|
10
10
|
|
11
11
|
def index
|
12
|
+
@page_title = resource_name.humanize
|
13
|
+
add_breadcrumb resource_name.humanize
|
14
|
+
|
12
15
|
set_index_params
|
13
16
|
set_filters
|
14
17
|
set_actions
|
@@ -48,15 +51,28 @@ module Avo
|
|
48
51
|
set_actions
|
49
52
|
|
50
53
|
@resource = @resource.hydrate(model: @model, view: :show, user: _current_user, params: params)
|
54
|
+
|
55
|
+
@page_title = @resource.default_panel_name
|
56
|
+
add_breadcrumb resource_name.humanize, resources_path(@resource.model_class)
|
57
|
+
add_breadcrumb @resource.model_title
|
51
58
|
end
|
52
59
|
|
53
60
|
def new
|
54
61
|
@model = @resource.model_class.new
|
55
62
|
@resource = @resource.hydrate(model: @model, view: :new, user: _current_user)
|
63
|
+
|
64
|
+
@page_title = @resource.default_panel_name
|
65
|
+
add_breadcrumb resource_name.humanize, resources_path(@resource.model_class)
|
66
|
+
add_breadcrumb t("avo.new").humanize
|
56
67
|
end
|
57
68
|
|
58
69
|
def edit
|
59
70
|
@resource = @resource.hydrate(model: @model, view: :edit, user: _current_user)
|
71
|
+
|
72
|
+
@page_title = @resource.default_panel_name
|
73
|
+
add_breadcrumb resource_name.humanize, resources_path(@resource.model_class)
|
74
|
+
add_breadcrumb @resource.model_title, resource_path(@resource.model)
|
75
|
+
add_breadcrumb t("avo.edit").humanize
|
60
76
|
end
|
61
77
|
|
62
78
|
def create
|
@@ -3,7 +3,11 @@ require_dependency "avo/application_controller"
|
|
3
3
|
module Avo
|
4
4
|
class HomeController < ApplicationController
|
5
5
|
def index
|
6
|
-
|
6
|
+
@page_title = "Get started"
|
7
|
+
|
8
|
+
if Avo.configuration.home_path.present?
|
9
|
+
redirect_to Avo.configuration.home_path
|
10
|
+
elsif !Rails.env.development?
|
7
11
|
redirect_to resources_path Avo::App.get_resources.min_by { |resource| resource.route_key }.model_class
|
8
12
|
end
|
9
13
|
end
|
@@ -21,12 +21,6 @@ module Avo
|
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
|
-
def panel(**args, &block)
|
25
|
-
render(Avo::PanelComponent.new(**args)) do |component|
|
26
|
-
capture(component, &block)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
24
|
def empty_state(resource_name)
|
31
25
|
render partial: "avo/partials/empty_state", locals: {resource_name: resource_name}
|
32
26
|
end
|
@@ -14,6 +14,7 @@
|
|
14
14
|
@import './../stylesheets/alerts.css';
|
15
15
|
@import './../stylesheets/loader.css';
|
16
16
|
@import './../stylesheets/pagination.css';
|
17
|
+
@import './../stylesheets/breadcrumbs.css';
|
17
18
|
|
18
19
|
@import './../stylesheets/components/status.css';
|
19
20
|
@import './../stylesheets/components/code.css';
|
@@ -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>
|