avo 2.30.1 → 2.31.0
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 +1 -1
- data/Gemfile.lock +9 -9
- data/app/assets/svgs/failed_to_load.svg +0 -1
- data/app/assets/svgs/grid-empty-state.svg +0 -1
- data/app/assets/svgs/table-empty-state.svg +0 -1
- data/app/components/avo/actions_component.rb +1 -1
- data/app/components/avo/field_wrapper_component.html.erb +2 -2
- data/app/components/avo/fields/common/files/controls_component.html.erb +29 -0
- data/app/components/avo/fields/common/files/controls_component.rb +19 -0
- data/app/components/avo/fields/common/files/list_viewer_component.html.erb +20 -0
- data/app/components/avo/fields/common/files/list_viewer_component.rb +41 -0
- data/app/components/avo/fields/common/files/view_type/grid_component.html.erb +27 -0
- data/app/components/avo/fields/common/{single_file_viewer_component.rb → files/view_type/grid_component.rb} +2 -9
- data/app/components/avo/fields/common/files/view_type/list_component.html.erb +22 -0
- data/app/components/avo/fields/common/files/view_type/list_component.rb +15 -0
- data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/file_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/files_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_many_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.html.erb +2 -2
- data/app/components/avo/item_switcher_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +1 -1
- data/app/components/avo/views/resource_edit_component.html.erb +4 -4
- data/app/components/avo/views/resource_index_component.html.erb +3 -3
- data/app/components/avo/views/resource_show_component.html.erb +3 -3
- data/app/controllers/avo/attachments_controller.rb +15 -8
- data/app/helpers/avo/application_helper.rb +8 -0
- data/app/views/avo/actions/show.html.erb +2 -2
- data/app/views/avo/associations/new.html.erb +2 -2
- data/app/views/avo/attachments/destroy.turbo_stream.erb +7 -0
- data/app/views/avo/dashboards/show.html.erb +2 -2
- data/app/views/avo/debug/index.html.erb +2 -2
- data/app/views/avo/home/index.html.erb +1 -1
- data/app/views/avo/partials/_view_toggle_button.html.erb +4 -0
- data/app/views/avo/private/design.html.erb +2 -2
- data/avo.gemspec +1 -1
- data/db/factories.rb +14 -0
- data/lib/avo/app.rb +1 -1
- data/lib/avo/concerns/policy_helpers.rb +31 -0
- data/lib/avo/engine.rb +0 -5
- data/lib/avo/fields/base_field.rb +4 -2
- data/lib/avo/fields/files_field.rb +4 -0
- data/lib/avo/filters/base_filter.rb +4 -0
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/tailwindcss/install_generator.rb +4 -1
- data/lib/generators/avo/templates/resource_tools/partial.tt +2 -2
- data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
- data/lib/generators/avo/templates/tool/view.tt +2 -2
- data/public/avo-assets/avo.base.css +25 -22
- metadata +14 -8
- data/app/components/avo/fields/common/files_list_viewer_component.html.erb +0 -5
- data/app/components/avo/fields/common/files_list_viewer_component.rb +0 -8
- data/app/components/avo/fields/common/single_file_viewer_component.html.erb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2d89325380615d00eeac9d1c507409b602452f320e96ce8818830b580cb5ffd
|
4
|
+
data.tar.gz: 787b185e5f37182a75dec5935ea5cd0a2d1cd1986981b79ff6393bfc021e649d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02eba26931bf6ea8300df3fc44006ad2390ddb3dd0ca6b474b438bd29953a5203e97f6b301297bc119572a8bef80341b62fcd7cc6c4ecf1dd7b065441ed168ff
|
7
|
+
data.tar.gz: fde51151f29f9c2c06d00cbdb0e16be8d594eb72c20669ad54944adb5d4f105098bf5f84b9a3878b3324837a3ea4086f067dc5030151161409f599699b06ae55
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (2.
|
4
|
+
avo (2.31.0)
|
5
5
|
actionview (>= 6.0)
|
6
6
|
active_link_to
|
7
7
|
activerecord (>= 6.0)
|
@@ -13,7 +13,7 @@ PATH
|
|
13
13
|
meta-tags
|
14
14
|
pagy
|
15
15
|
turbo-rails
|
16
|
-
view_component
|
16
|
+
view_component (>= 2.54.0)
|
17
17
|
zeitwerk (>= 2.6.2)
|
18
18
|
|
19
19
|
GEM
|
@@ -196,7 +196,7 @@ GEM
|
|
196
196
|
highline (2.1.0)
|
197
197
|
hightop (0.3.0)
|
198
198
|
activesupport (>= 5.2)
|
199
|
-
hotwire-livereload (1.2.
|
199
|
+
hotwire-livereload (1.2.3)
|
200
200
|
listen (>= 3.0.0)
|
201
201
|
rails (>= 6.0.0)
|
202
202
|
html_tokenizer (0.0.7)
|
@@ -233,10 +233,10 @@ GEM
|
|
233
233
|
json (2.6.2)
|
234
234
|
launchy (2.5.2)
|
235
235
|
addressable (~> 2.8)
|
236
|
-
listen (3.
|
236
|
+
listen (3.8.0)
|
237
237
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
238
238
|
rb-inotify (~> 0.9, >= 0.9.10)
|
239
|
-
loofah (2.
|
239
|
+
loofah (2.20.0)
|
240
240
|
crass (~> 1.0.2)
|
241
241
|
nokogiri (>= 1.5.9)
|
242
242
|
mail (2.8.1)
|
@@ -268,7 +268,7 @@ GEM
|
|
268
268
|
timeout
|
269
269
|
net-smtp (0.3.3)
|
270
270
|
net-protocol
|
271
|
-
nio4r (2.5.
|
271
|
+
nio4r (2.5.9)
|
272
272
|
nokogiri (1.14.3)
|
273
273
|
mini_portile2 (~> 2.8.0)
|
274
274
|
racc (~> 1.4)
|
@@ -331,7 +331,7 @@ GEM
|
|
331
331
|
activerecord (>= 6.0.4)
|
332
332
|
activesupport (>= 6.0.4)
|
333
333
|
i18n
|
334
|
-
rb-fsevent (0.11.
|
334
|
+
rb-fsevent (0.11.2)
|
335
335
|
rb-inotify (0.10.1)
|
336
336
|
ffi (~> 1.0)
|
337
337
|
redis (4.8.1)
|
@@ -421,7 +421,7 @@ GEM
|
|
421
421
|
tzinfo (2.0.6)
|
422
422
|
concurrent-ruby (~> 1.0)
|
423
423
|
unicode-display_width (2.4.0)
|
424
|
-
view_component (
|
424
|
+
view_component (3.0.0)
|
425
425
|
activesupport (>= 5.2.0, < 8.0)
|
426
426
|
concurrent-ruby (~> 1.0)
|
427
427
|
method_source (~> 1.0)
|
@@ -483,7 +483,7 @@ DEPENDENCIES
|
|
483
483
|
gem-release
|
484
484
|
groupdate
|
485
485
|
hightop
|
486
|
-
hotwire-livereload (~> 1.
|
486
|
+
hotwire-livereload (~> 1.2)
|
487
487
|
htmlbeautifier
|
488
488
|
httparty
|
489
489
|
i18n-tasks (~> 1.0.12)
|
@@ -22,7 +22,6 @@
|
|
22
22
|
<feColorMatrix type="matrix" values="0 0 0 0 0.788235 0 0 0 0 0.803922 0 0 0 0 0.85098 0 0 0 0.349 0"/>
|
23
23
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_577_1090"/>
|
24
24
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_577_1090" result="shape"/>
|
25
|
-
</filter>
|
26
25
|
<filter id="filter1_d_577_1090" x="38.6401" y="0" width="170.72" height="78.1333" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
27
26
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
28
27
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
class: classes,
|
3
3
|
style: style,
|
4
4
|
data: data do %>
|
5
|
-
<div class="h-full <% if stacked? %> md:pt-4 <% else %> md:pt-0 md:h-14 <% end %> pt-4 flex self-start items-center <%= @field.get_html(:classes, view: view, element: :label) %> w-48 <% if compact? %> md:w-48 xl:w-64 <% else %> md:w-64 <% end %> px-6 uppercase font-semibold text-gray-500 text-sm" data-slot="label">
|
5
|
+
<div class="h-full <% if stacked? %> md:pt-4 <% else %> md:pt-0 md:h-14 <% end %> pt-4 flex self-start items-center flex-shrink-0 <%= @field.get_html(:classes, view: view, element: :label) %> w-48 <% if compact? %> md:w-48 xl:w-64 <% else %> md:w-64 <% end %> px-6 uppercase font-semibold text-gray-500 text-sm" data-slot="label">
|
6
6
|
<% if form.present? %>
|
7
7
|
<%= form.label field.id, label %>
|
8
8
|
<% else %>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<% if on_edit? && field.is_required? %> <span class="text-red-600 ml-1">*</span> <% end %>
|
12
12
|
</div>
|
13
13
|
<div class="flex-1 flex flex-row md:min-h-inherit py-2 <% if stacked? %> pb-4 <% else %><% end %> px-6 <%= @field.get_html(:classes, view: view, element: :content) %>" data-slot="value">
|
14
|
-
<div class="self-center <%
|
14
|
+
<div class="self-center w-full <% unless full_width? || compact? || stacked? %> md:w-8/12 <% end %>">
|
15
15
|
<% if on_show? %>
|
16
16
|
<% if field.value.blank? and dash_if_blank %>
|
17
17
|
—
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<div class="flex">
|
2
|
+
<% if can_download_file? %>
|
3
|
+
<%= a_link Rails.application.routes.url_helpers.rails_blob_path(file, only_path: true, disposition: :attachment),
|
4
|
+
icon: 'heroicons/outline/download',
|
5
|
+
color: :primary,
|
6
|
+
download: true,
|
7
|
+
class: 'text-center',
|
8
|
+
title: t('avo.download_file'),
|
9
|
+
data: { tippy: :tooltip },
|
10
|
+
compact: true,
|
11
|
+
size: :xs %>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
|
+
<div>
|
15
|
+
<% if can_delete_file? %>
|
16
|
+
<%= a_link destroy_path,
|
17
|
+
icon: 'heroicons/outline/trash',
|
18
|
+
color: :red,
|
19
|
+
compact: true,
|
20
|
+
size: :xs,
|
21
|
+
class: 'text-center',
|
22
|
+
title: t('avo.delete_file', item: file.filename),
|
23
|
+
data: {
|
24
|
+
turbo_method: :delete,
|
25
|
+
turbo_confirm: t('avo.are_you_sure'),
|
26
|
+
tippy: :tooltip
|
27
|
+
} %>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Fields::Common::Files::ControlsComponent < ViewComponent::Base
|
4
|
+
include Avo::ApplicationHelper
|
5
|
+
include Avo::Fields::Concerns::FileAuthorization
|
6
|
+
|
7
|
+
attr_reader :file, :field, :resource
|
8
|
+
delegate :id, to: :field
|
9
|
+
|
10
|
+
def initialize(field:, file:, resource:)
|
11
|
+
@field = field
|
12
|
+
@file = file
|
13
|
+
@resource = resource
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy_path
|
17
|
+
Avo::Services::URIService.parse(@resource.record_path).append_paths("active_storage_attachments", id, file.id).to_s
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%= content_tag :div, class: wrapper_classes do %>
|
2
|
+
<%= turbo_frame_tag @field.id do %>
|
3
|
+
<% unless @field.hide_view_type_switcher %>
|
4
|
+
<div class="justify-self-end flex justify-end items-center space-x-3">
|
5
|
+
<%= render partial: 'avo/partials/view_toggle_button',
|
6
|
+
locals: {
|
7
|
+
available_view_types: available_view_types,
|
8
|
+
view_type: view_type,
|
9
|
+
turbo_frame: @field.id,
|
10
|
+
}
|
11
|
+
%>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
<div class="<%= classes %>">
|
15
|
+
<% @field.value.attachments.each do |file| %>
|
16
|
+
<%= render view_type_component(file) %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Fields::Common::Files::ListViewerComponent < ViewComponent::Base
|
4
|
+
include Turbo::FramesHelper
|
5
|
+
|
6
|
+
attr_reader :field, :resource
|
7
|
+
|
8
|
+
def initialize(field:, resource:)
|
9
|
+
@field = field
|
10
|
+
@resource = resource
|
11
|
+
end
|
12
|
+
|
13
|
+
def classes
|
14
|
+
base_classes = "py-4 rounded-xl max-w-full"
|
15
|
+
|
16
|
+
view_type_classes = if view_type == :list
|
17
|
+
"flex flex-col space-y-2"
|
18
|
+
else
|
19
|
+
"relative grid xs:grid-cols-2 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6 gap-6"
|
20
|
+
end
|
21
|
+
|
22
|
+
"#{base_classes} #{view_type_classes}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def wrapper_classes
|
26
|
+
(field.stacked && !field.hide_view_type_switcher) ? "-mt-9" : ""
|
27
|
+
end
|
28
|
+
|
29
|
+
def available_view_types
|
30
|
+
[:list, :grid]
|
31
|
+
end
|
32
|
+
|
33
|
+
def view_type_component(file)
|
34
|
+
component = "Avo::Fields::Common::Files::ViewType::#{view_type.to_s.capitalize}Component".constantize
|
35
|
+
component.new(field: field, resource: resource, file: file)
|
36
|
+
end
|
37
|
+
|
38
|
+
def view_type
|
39
|
+
(resource.params.dig(:view_type) || field.view_type).to_sym
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div id="<%= dom_id file %>" class="relative min-h-full max-w-full flex-1 flex flex-col justify-between space-y-2">
|
2
|
+
<% if file.present? %>
|
3
|
+
<div class="flex flex-col justify-between h-full">
|
4
|
+
<% if file.representable? && is_image? %>
|
5
|
+
<%= image_tag helpers.main_app.url_for(file), class: 'rounded-lg object-cover w-full aspect-video' %>
|
6
|
+
<% elsif is_audio? %>
|
7
|
+
<%= audio_tag(helpers.main_app.url_for(file), controls: true, preload: false, class: 'w-full') %>
|
8
|
+
<% elsif is_video? %>
|
9
|
+
<%= video_tag(helpers.main_app.url_for(file), controls: true, preload: false, class: 'w-full') %>
|
10
|
+
<% else %>
|
11
|
+
<div class="relative flex flex-col justify-evenly items-center px-2 rounded-lg border bg-white border-gray-500 min-h-24">
|
12
|
+
<div class="flex flex-col justify-center items-center w-full">
|
13
|
+
<%= helpers.svg 'document-text', class: 'h-10 text-gray-600 mb-2' %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
17
|
+
<% if field.display_filename %>
|
18
|
+
<span class="text-gray-500 mt-1 text-sm truncate" title="<%= file.filename %>"><%= file.filename %></span>
|
19
|
+
<% end %>
|
20
|
+
</div>
|
21
|
+
<div class="flex space-x-2">
|
22
|
+
<%= render Avo::Fields::Common::Files::ControlsComponent.new(field: field, file: file, resource: resource) %>
|
23
|
+
</div>
|
24
|
+
<% else %>
|
25
|
+
–
|
26
|
+
<% end %>
|
27
|
+
</div>
|
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class Avo::Fields::Common::
|
4
|
-
|
5
|
-
include Avo::Fields::Concerns::FileAuthorization
|
6
|
-
|
7
|
-
attr_reader :field
|
3
|
+
class Avo::Fields::Common::Files::ViewType::GridComponent < ViewComponent::Base
|
4
|
+
attr_reader :field, :resource
|
8
5
|
|
9
6
|
def initialize(field:, resource:, file: nil)
|
10
7
|
@file = file
|
@@ -12,10 +9,6 @@ class Avo::Fields::Common::SingleFileViewerComponent < ViewComponent::Base
|
|
12
9
|
@resource = resource
|
13
10
|
end
|
14
11
|
|
15
|
-
def destroy_path
|
16
|
-
Avo::Services::URIService.parse(@resource.record_path).append_paths("active_storage_attachments", id, file.id).to_s
|
17
|
-
end
|
18
|
-
|
19
12
|
def id
|
20
13
|
field.id
|
21
14
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<div id="<%= dom_id file %>" class="relative min-h-full max-w-full flex-1 flex">
|
2
|
+
<% if file.present? %>
|
3
|
+
<div class="grid grid-cols-6 gap-2 items-center max-w-full w-full">
|
4
|
+
<div class="col-span-4 flex-1 flex flex-row items-center text-gray-700 overflow-x-auto mac-styled-scrollbar ">
|
5
|
+
<div class="rounded-full bg-slate-100 border border-gray-500 p-1.5 flex items-center justify-center">
|
6
|
+
<%= helpers.svg icon_for_file, class: "h-5 text-gray-600" %>
|
7
|
+
</div>
|
8
|
+
<p class="items-center h-full p-2 flex-shrink-0">
|
9
|
+
<%= file.filename %>
|
10
|
+
</p>
|
11
|
+
</div>
|
12
|
+
<div class="text-gray-700 flex-shrink-0 text-sm">
|
13
|
+
<%= helpers.number_to_human_size(file.byte_size) %>
|
14
|
+
</div>
|
15
|
+
<div class="flex space-x-2 justify-end col-span-1 flex-shrink-0">
|
16
|
+
<%= render Avo::Fields::Common::Files::ControlsComponent.new(field: field, file: file, resource: resource) %>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
<% else %>
|
20
|
+
–
|
21
|
+
<% end %>
|
22
|
+
</div>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Avo::Fields::Common::Files::ViewType::ListComponent < Avo::Fields::Common::Files::ViewType::GridComponent
|
4
|
+
def icon_for_file
|
5
|
+
if is_image?
|
6
|
+
"photo"
|
7
|
+
elsif is_audio?
|
8
|
+
"speaker-wave"
|
9
|
+
elsif is_video?
|
10
|
+
"video-camera"
|
11
|
+
else
|
12
|
+
"document"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args do %>
|
2
2
|
<% if @field.value.present? %>
|
3
3
|
<div class="mb-2">
|
4
|
-
<%= render Avo::Fields::Common::
|
4
|
+
<%= render Avo::Fields::Common::Files::ViewType::GridComponent.new resource: @resource, field: @field %>
|
5
5
|
</div>
|
6
6
|
<% end %>
|
7
7
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<%= render Avo::Fields::Common::
|
2
|
+
<%= render Avo::Fields::Common::Files::ListViewerComponent.new(field: @field, resource: @resource) if @field.value.present? %>
|
3
3
|
|
4
4
|
<% if can_upload_file? %>
|
5
5
|
<div class="mt-2">
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<%= field_wrapper **field_wrapper_args, full_width: true do %>
|
2
|
-
<%= render Avo::Fields::Common::
|
2
|
+
<%= render Avo::Fields::Common::Files::ListViewerComponent.new(field: @field, resource: @resource) if @field.value.present? %>
|
3
3
|
<% end %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
</turbo-frame>
|
5
5
|
<% else %>
|
6
6
|
<%= render Avo::PanelComponent.new(name: @field.name) do |c| %>
|
7
|
-
<% c.
|
7
|
+
<% c.with_tools do %>
|
8
8
|
<% if !@field.is_readonly? && !@field.is_disabled? && can_attach? %>
|
9
9
|
<%= a_link attach_path,
|
10
10
|
icon: 'heroicons/outline/link',
|
@@ -25,7 +25,7 @@
|
|
25
25
|
<% end %>
|
26
26
|
<% end %>
|
27
27
|
|
28
|
-
<% c.
|
28
|
+
<% c.with_body do %>
|
29
29
|
<div class="py-8 flex justify-center items-center">
|
30
30
|
<%= empty_state by_association: params[:related_name].present? %>
|
31
31
|
</div>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% end %>
|
5
5
|
<% elsif item.is_panel? %>
|
6
6
|
<%= render Avo::PanelComponent.new(name: item.name, description: item.description, index: index) do |c| %>
|
7
|
-
<% c.
|
7
|
+
<% c.with_body do %>
|
8
8
|
<div class="divide-y">
|
9
9
|
<% item.visible_items.each_with_index do |field, index| %>
|
10
10
|
<%= render field
|
@@ -119,7 +119,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
|
|
119
119
|
end
|
120
120
|
|
121
121
|
if filtered_fields.present?
|
122
|
-
filtered_fields.find { |f| f.id == @reflection.name }.
|
122
|
+
filtered_fields.find { |f| f.id == @reflection.name }.is_readonly?
|
123
123
|
else
|
124
124
|
false
|
125
125
|
end
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
|
20
20
|
<%= content_tag :div, class: 'space-y-12' do %>
|
21
21
|
<%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
22
|
-
<% c.
|
22
|
+
<% c.with_tools do %>
|
23
23
|
<%= a_link back_path,
|
24
24
|
style: :text,
|
25
25
|
icon: 'arrow-left' do %>
|
@@ -56,7 +56,7 @@
|
|
56
56
|
<%# Extract the main panel and display the fields here. %>
|
57
57
|
<%# This way we'll be able to render the footer buttons under the main fields. %>
|
58
58
|
<% if main_panel.present? %>
|
59
|
-
<% c.
|
59
|
+
<% c.with_body do %>
|
60
60
|
<div class="divide-y">
|
61
61
|
<% main_panel.items.each_with_index do |field, index| %>
|
62
62
|
<%= render field
|
@@ -69,12 +69,12 @@
|
|
69
69
|
<% end %>
|
70
70
|
<% end %>
|
71
71
|
<% if sidebar.present? %>
|
72
|
-
<% c.
|
72
|
+
<% c.with_sidebar do %>
|
73
73
|
<%= render sidebar_component form: form %>
|
74
74
|
<% end %>
|
75
75
|
<% end %>
|
76
76
|
<% if Avo.configuration.buttons_on_form_footers %>
|
77
|
-
<% c.
|
77
|
+
<% c.with_footer_tools do %>
|
78
78
|
<div class="mt-4">
|
79
79
|
<%= a_link back_path,
|
80
80
|
style: :text,
|
@@ -5,7 +5,7 @@
|
|
5
5
|
**@resource.stimulus_data_attributes
|
6
6
|
} do %>
|
7
7
|
<%= render Avo::PanelComponent.new(name: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
|
8
|
-
<% c.
|
8
|
+
<% c.with_tools do %>
|
9
9
|
<% if can_attach? %>
|
10
10
|
<%= a_link attach_path,
|
11
11
|
icon: 'heroicons/outline/link',
|
@@ -29,7 +29,7 @@
|
|
29
29
|
<% end %>
|
30
30
|
<% end %>
|
31
31
|
<% end %>
|
32
|
-
<% c.
|
32
|
+
<% c.with_body do %>
|
33
33
|
<div class="flex flex-col xs:flex-row xs:justify-between space-y-2 xs:space-y-0 py-4 <%= 'hidden' if @resource.search_query.nil? && @filters.empty? && available_view_types.count <= 1 %>">
|
34
34
|
<% if show_search_input %>
|
35
35
|
<div class="flex items-center px-4 w-64">
|
@@ -56,7 +56,7 @@
|
|
56
56
|
<% end %>
|
57
57
|
<% end %>
|
58
58
|
<% end %>
|
59
|
-
<% c.
|
59
|
+
<% c.with_bare_content do %>
|
60
60
|
<% if view_type.to_sym == :table %>
|
61
61
|
<% if @models.present? %>
|
62
62
|
<div class="mt-4">
|
@@ -8,7 +8,7 @@
|
|
8
8
|
**@resource.stimulus_data_attributes
|
9
9
|
} do %>
|
10
10
|
<%= render Avo::PanelComponent.new(name: title, description: @resource.resource_description, display_breadcrumbs: @reflection.blank?, index: 0, data: { panel_id: "main" }) do |c| %>
|
11
|
-
<% c.
|
11
|
+
<% c.with_tools do %>
|
12
12
|
<% if @resource.has_show_controls? %>
|
13
13
|
<% @resource.render_show_controls.each do |control| %>
|
14
14
|
<% if control.back_button? %>
|
@@ -155,7 +155,7 @@
|
|
155
155
|
<% end %>
|
156
156
|
<% end %>
|
157
157
|
<% if main_panel.present? %>
|
158
|
-
<% c.
|
158
|
+
<% c.with_body do %>
|
159
159
|
<%# the overflow helps with long values %>
|
160
160
|
<div class="divide-y overflow-auto">
|
161
161
|
<% main_panel.items.each_with_index do |field, index| %>
|
@@ -169,7 +169,7 @@
|
|
169
169
|
<% end %>
|
170
170
|
<% end %>
|
171
171
|
<% if sidebar.present? %>
|
172
|
-
<% c.
|
172
|
+
<% c.with_sidebar do %>
|
173
173
|
<%= render sidebar_component %>
|
174
174
|
<% end %>
|
175
175
|
<% end %>
|
@@ -23,17 +23,24 @@ module Avo
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def destroy
|
26
|
-
|
26
|
+
if authorized_to :delete
|
27
|
+
attachment = ActiveStorage::Attachment.find(params[:attachment_id])
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
flash[:notice] = if attachment.present?
|
30
|
+
@destroyed = attachment.destroy
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
t("avo.attachment_destroyed")
|
33
|
+
else
|
34
|
+
t("avo.failed_to_find_attachment")
|
35
|
+
end
|
35
36
|
else
|
36
|
-
|
37
|
+
flash[:notice] = t("avo.not_authorized")
|
38
|
+
end
|
39
|
+
|
40
|
+
respond_to do |format|
|
41
|
+
format.turbo_stream do
|
42
|
+
render "destroy"
|
43
|
+
end
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
@@ -111,6 +111,14 @@ module Avo
|
|
111
111
|
Avo::Engine.routes.find_script_name(params.permit!.to_h.symbolize_keys)
|
112
112
|
end
|
113
113
|
|
114
|
+
def decode_filter_params(encoded_params)
|
115
|
+
Avo::Filters::BaseFilter.decode_filters(encoded_params)
|
116
|
+
end
|
117
|
+
|
118
|
+
def encode_filter_params(filter_params)
|
119
|
+
Avo::Filters::BaseFilter.encode_filters(filter_params)
|
120
|
+
end
|
121
|
+
|
114
122
|
private
|
115
123
|
|
116
124
|
# Taken from the original library
|
@@ -14,7 +14,7 @@
|
|
14
14
|
data: @action.class.form_data_attributes do |form|
|
15
15
|
%>
|
16
16
|
<%= render Avo::ModalComponent.new do |c| %>
|
17
|
-
<% c.
|
17
|
+
<% c.with_heading do %>
|
18
18
|
<%= @action.action_name %>
|
19
19
|
<% end %>
|
20
20
|
<div class="flex-1 flex">
|
@@ -33,7 +33,7 @@
|
|
33
33
|
<% end %>
|
34
34
|
</div>
|
35
35
|
<% end %>
|
36
|
-
<% c.
|
36
|
+
<% c.with_controls do %>
|
37
37
|
<%= a_button type: :button,
|
38
38
|
data: { action: 'click->modal#close' },
|
39
39
|
size: :sm,
|
@@ -11,7 +11,7 @@
|
|
11
11
|
'turbo-frame': '_top'
|
12
12
|
} do |form| %>
|
13
13
|
<%= render Avo::ModalComponent.new do |c| %>
|
14
|
-
<% c.
|
14
|
+
<% c.with_heading do %>
|
15
15
|
<%= t 'avo.choose_item', item: @related_resource.name.downcase %>
|
16
16
|
<% end %>
|
17
17
|
|
@@ -39,7 +39,7 @@
|
|
39
39
|
<% end %>
|
40
40
|
</div>
|
41
41
|
|
42
|
-
<% c.
|
42
|
+
<% c.with_controls do %>
|
43
43
|
<%= a_button 'data-action': 'click->modal#close', size: :sm, style: :outline, color: :gray do %>
|
44
44
|
<%= t('avo.cancel') %>
|
45
45
|
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%= render Avo::PanelComponent.new(name: @dashboard.name, description: @dashboard.description) do |c| %>
|
2
|
-
<% c.
|
2
|
+
<% c.with_bare_content do %>
|
3
3
|
<% if @dashboard.items.present? %>
|
4
4
|
<div class="min-h-24">
|
5
5
|
<%= content_tag(:div, class: "grid gap-4 grid-cols-1 #{@dashboard.classes}") do %>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
<div class="w-full h-full">
|
24
24
|
<% if Rails.env.development? %>
|
25
25
|
<%= render Avo::PanelComponent.new do |c| %>
|
26
|
-
<% c.
|
26
|
+
<% c.with_body do %>
|
27
27
|
<div class="p-6">
|
28
28
|
<%= t 'avo.empty_dashboard_message' %>. <%= link_to 'Docs', 'https://docs.avohq.io/2.0/dashboards.html', target: '_blank' %>
|
29
29
|
</div>
|
@@ -15,9 +15,9 @@
|
|
15
15
|
%>
|
16
16
|
<div class="flex flex-col">
|
17
17
|
<%= render Avo::PanelComponent.new(name: 'Debug Avo', description: 'Use this page to debug the Avo license.') do |c| %>
|
18
|
-
<% c.
|
18
|
+
<% c.with_tools do %>
|
19
19
|
<% end %>
|
20
|
-
<% c.
|
20
|
+
<% c.with_bare_content do %>
|
21
21
|
<div class="grid gap-4 sm:grid-cols-3">
|
22
22
|
<div class="relative flex flex-col bg-white rounded shadow-panel p-4 space-y-4 h-full col-span-1">
|
23
23
|
<div class="flex justify-between w-full">
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
2
|
<%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
|
3
|
-
<% c.
|
3
|
+
<% c.with_body do %>
|
4
4
|
<div class="flex flex-col justify-between py-6 min-h-24">
|
5
5
|
<div class="px-6 space-y-4">
|
6
6
|
<h3>About</h3>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
2
|
<%= render Avo::PanelComponent.new(name: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
|
3
|
-
<% c.
|
3
|
+
<% c.with_tools do %>
|
4
4
|
<%= a_link('/admin', icon: 'arrow-left', color: :green, style: :primary, is_link: true) do %>
|
5
5
|
Primary
|
6
6
|
<% end %>
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<% end %>
|
19
19
|
<% end %>
|
20
20
|
|
21
|
-
<% c.
|
21
|
+
<% c.with_body do %>
|
22
22
|
<div class="flex flex-col justify-between py-6 min-h-24">
|
23
23
|
<%= render 'links_and_buttons' %>
|
24
24
|
</div>
|
data/avo.gemspec
CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_dependency "zeitwerk", ">= 2.6.2"
|
39
39
|
spec.add_dependency "httparty"
|
40
40
|
spec.add_dependency "active_link_to"
|
41
|
-
spec.add_dependency "view_component"
|
41
|
+
spec.add_dependency "view_component", ">= 2.54.0"
|
42
42
|
spec.add_dependency "turbo-rails"
|
43
43
|
spec.add_dependency "addressable"
|
44
44
|
spec.add_dependency "meta-tags"
|
data/db/factories.rb
CHANGED
@@ -42,6 +42,20 @@ FactoryBot.define do
|
|
42
42
|
progress { Faker::Number.between(from: 0, to: 100) }
|
43
43
|
end
|
44
44
|
|
45
|
+
trait :with_files do
|
46
|
+
after(:create) do |project|
|
47
|
+
["watch.jpg", "dummy-video.mp4"].each do |filename|
|
48
|
+
file = Rails.root.join("db", "seed_files", filename)
|
49
|
+
project.files.attach(io: file.open, filename: filename)
|
50
|
+
end
|
51
|
+
|
52
|
+
["dummy-file.txt", "dummy-audio.mp3"].each do |filename|
|
53
|
+
file = Avo::Engine.root.join("spec", "dummy", filename)
|
54
|
+
project.files.attach(io: file.open, filename: filename)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
45
59
|
factory :comment do
|
46
60
|
body { Faker::Lorem.paragraphs(number: rand(4...10)).join(" ") }
|
47
61
|
posted_at { Time.now - rand(10...365).days }
|
data/lib/avo/app.rb
CHANGED
@@ -63,7 +63,7 @@ module Avo
|
|
63
63
|
if Rails::VERSION::MAJOR === 6
|
64
64
|
ActiveStorage::Current.host = request.base_url
|
65
65
|
elsif Rails::VERSION::MAJOR === 7
|
66
|
-
ActiveStorage::Current.url_options = request.
|
66
|
+
ActiveStorage::Current.url_options = {protocol: request.protocol, host: request.host, port: request.port}
|
67
67
|
end
|
68
68
|
end
|
69
69
|
rescue => exception
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Avo
|
2
|
+
module Concerns
|
3
|
+
module PolicyHelpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
def inherit_association_from_policy(association_name, policy_class)
|
8
|
+
[:create, :edit, :update, :destroy, :show, :reorder, :act_on].each do |method_action|
|
9
|
+
define_policy_method(method_action, association_name, policy_class)
|
10
|
+
end
|
11
|
+
|
12
|
+
define_policy_method("view", association_name, policy_class, "index")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Define a method for the given action and association name.
|
18
|
+
# Call the policy class with the given action passing the user and record.
|
19
|
+
# Example:
|
20
|
+
# def create_team_members?
|
21
|
+
# TeamMemberPolicy.new(user, record).create?
|
22
|
+
# end
|
23
|
+
def define_policy_method(method_action, association_name, policy_class, policy_action = method_action)
|
24
|
+
define_method "#{method_action}_#{association_name}?" do
|
25
|
+
policy_class.new(user, record).send "#{policy_action}?"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/avo/engine.rb
CHANGED
@@ -14,11 +14,6 @@ Gem.loaded_specs["avo"].dependencies.each do |d|
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
# In development we should load the engine so we get the autoload for components
|
18
|
-
if ENV["RAILS_ENV"] === "development"
|
19
|
-
require "view_component/engine"
|
20
|
-
end
|
21
|
-
|
22
17
|
module Avo
|
23
18
|
class Engine < ::Rails::Engine
|
24
19
|
isolate_namespace Avo
|
@@ -40,7 +40,6 @@ module Avo
|
|
40
40
|
attr_reader :stacked
|
41
41
|
|
42
42
|
# Private options
|
43
|
-
attr_reader :updatable
|
44
43
|
attr_reader :computable # if allowed to be computable
|
45
44
|
attr_reader :computed # if block is present
|
46
45
|
attr_reader :computed_value # the value after computation
|
@@ -86,7 +85,6 @@ module Avo
|
|
86
85
|
|
87
86
|
@args = args
|
88
87
|
|
89
|
-
@updatable = !readonly
|
90
88
|
@computable = true
|
91
89
|
@computed = block.present?
|
92
90
|
@computed_value = nil
|
@@ -257,6 +255,10 @@ module Avo
|
|
257
255
|
!visible_in_reflection?
|
258
256
|
end
|
259
257
|
|
258
|
+
def updatable
|
259
|
+
!is_readonly? && visible?
|
260
|
+
end
|
261
|
+
|
260
262
|
private
|
261
263
|
|
262
264
|
def model_or_class(model)
|
@@ -6,6 +6,8 @@ module Avo
|
|
6
6
|
attr_accessor :direct_upload
|
7
7
|
attr_accessor :accept
|
8
8
|
attr_reader :display_filename
|
9
|
+
attr_reader :view_type
|
10
|
+
attr_reader :hide_view_type_switcher
|
9
11
|
|
10
12
|
def initialize(id, **args, &block)
|
11
13
|
super(id, **args, &block)
|
@@ -15,6 +17,8 @@ module Avo
|
|
15
17
|
@direct_upload = args[:direct_upload].present? ? args[:direct_upload] : false
|
16
18
|
@accept = args[:accept].present? ? args[:accept] : nil
|
17
19
|
@display_filename = args[:display_filename].nil? ? true : args[:display_filename]
|
20
|
+
@view_type = args[:view_type] || :grid
|
21
|
+
@hide_view_type_switcher = args[:hide_view_type_switcher]
|
18
22
|
end
|
19
23
|
|
20
24
|
def view_component_name
|
data/lib/avo/version.rb
CHANGED
@@ -21,7 +21,7 @@ module Generators
|
|
21
21
|
end
|
22
22
|
|
23
23
|
if Rails.root.join("Procfile.dev").exist?
|
24
|
-
append_to_file "Procfile.dev", "avo_css:
|
24
|
+
append_to_file "Procfile.dev", "avo_css: yarn avo:tailwindcss --watch\n"
|
25
25
|
else
|
26
26
|
say "Add default Procfile.dev"
|
27
27
|
copy_file template_path("Procfile.dev"), "Procfile.dev"
|
@@ -38,6 +38,9 @@ module Generators
|
|
38
38
|
|
39
39
|
say "Adding the CSS asset to the partial"
|
40
40
|
prepend_to_file Rails.root.join("app", "views", "avo", "partials", "_pre_head.html.erb"), "<%= stylesheet_link_tag \"avo.tailwind.css\", media: \"all\" %>"
|
41
|
+
|
42
|
+
say "Ensure you have the following script in your package.json file.", :yellow
|
43
|
+
say %("scripts": { "avo:tailwindcss": "tailwindcss -i ./app/assets/stylesheets/avo.tailwind.css -o ./app/assets/builds/avo.tailwind.css --minify" }), :green
|
41
44
|
end
|
42
45
|
|
43
46
|
no_tasks do
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
2
|
<%%= render Avo::PanelComponent.new(name: "<%= human_name %>") do |c| %>
|
3
|
-
<%% c.
|
3
|
+
<%% c.with_tools do %>
|
4
4
|
<%%= a_link('/avo', icon: 'heroicons/solid/academic-cap', color: :primary, style: :primary) do %>
|
5
5
|
Dummy link
|
6
6
|
<%% end %>
|
7
7
|
<%% end %>
|
8
8
|
|
9
|
-
<%% c.
|
9
|
+
<%% c.with_body do %>
|
10
10
|
<div class="flex flex-col p-4 min-h-24">
|
11
11
|
<div class="space-y-4">
|
12
12
|
<h3>🪧 This partial is waiting to be updated</h3>
|
@@ -1,2 +1,2 @@
|
|
1
1
|
web: bin/rails server -p 3000
|
2
|
-
avo_css:
|
2
|
+
avo_css: yarn avo:tailwindcss --watch
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<div class="flex flex-col">
|
2
2
|
<%%= render Avo::PanelComponent.new(name: '<%= human_name %>', display_breadcrumbs: true) do |c| %>
|
3
|
-
<%% c.
|
3
|
+
<%% c.with_tools do %>
|
4
4
|
<div class="text-sm italic">This is the panels tools section.</div>
|
5
5
|
<%% end %>
|
6
6
|
|
7
|
-
<%% c.
|
7
|
+
<%% c.with_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>What a nice new tool 👋</h3>
|
@@ -6386,6 +6386,10 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
6386
6386
|
grid-column:1 / -1
|
6387
6387
|
}
|
6388
6388
|
|
6389
|
+
.col-span-4{
|
6390
|
+
grid-column:span 4 / span 4
|
6391
|
+
}
|
6392
|
+
|
6389
6393
|
.float-right{
|
6390
6394
|
float:right
|
6391
6395
|
}
|
@@ -6595,6 +6599,10 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
6595
6599
|
margin-bottom:0.25rem
|
6596
6600
|
}
|
6597
6601
|
|
6602
|
+
.-mt-9{
|
6603
|
+
margin-top:-2.25rem
|
6604
|
+
}
|
6605
|
+
|
6598
6606
|
.block{
|
6599
6607
|
display:block
|
6600
6608
|
}
|
@@ -6631,6 +6639,10 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
6631
6639
|
aspect-ratio:1 / 1
|
6632
6640
|
}
|
6633
6641
|
|
6642
|
+
.aspect-video{
|
6643
|
+
aspect-ratio:16 / 9
|
6644
|
+
}
|
6645
|
+
|
6634
6646
|
.h-36{
|
6635
6647
|
height:9rem
|
6636
6648
|
}
|
@@ -6711,10 +6723,6 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
6711
6723
|
height:2.25rem
|
6712
6724
|
}
|
6713
6725
|
|
6714
|
-
.max-h-\[42rem\]{
|
6715
|
-
max-height:42rem
|
6716
|
-
}
|
6717
|
-
|
6718
6726
|
.max-h-full{
|
6719
6727
|
max-height:100%
|
6720
6728
|
}
|
@@ -6918,6 +6926,10 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
6918
6926
|
grid-template-columns:repeat(1, minmax(0, 1fr))
|
6919
6927
|
}
|
6920
6928
|
|
6929
|
+
.grid-cols-6{
|
6930
|
+
grid-template-columns:repeat(6, minmax(0, 1fr))
|
6931
|
+
}
|
6932
|
+
|
6921
6933
|
.flex-row{
|
6922
6934
|
flex-direction:row
|
6923
6935
|
}
|
@@ -6998,10 +7010,6 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
6998
7010
|
gap:1.5rem
|
6999
7011
|
}
|
7000
7012
|
|
7001
|
-
.gap-3{
|
7002
|
-
gap:0.75rem
|
7003
|
-
}
|
7004
|
-
|
7005
7013
|
.gap-1{
|
7006
7014
|
gap:0.25rem
|
7007
7015
|
}
|
@@ -7066,12 +7074,6 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
7066
7074
|
margin-left:calc(0.75rem * calc(1 - var(--tw-space-x-reverse)))
|
7067
7075
|
}
|
7068
7076
|
|
7069
|
-
.space-y-3 > :not([hidden]) ~ :not([hidden]){
|
7070
|
-
--tw-space-y-reverse:0;
|
7071
|
-
margin-top:calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
|
7072
|
-
margin-bottom:calc(0.75rem * var(--tw-space-y-reverse))
|
7073
|
-
}
|
7074
|
-
|
7075
7077
|
.divide-y > :not([hidden]) ~ :not([hidden]){
|
7076
7078
|
--tw-divide-y-reverse:0;
|
7077
7079
|
border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
@@ -7561,6 +7563,11 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
7561
7563
|
background-color:rgb(94 100 110 / var(--tw-bg-opacity))
|
7562
7564
|
}
|
7563
7565
|
|
7566
|
+
.bg-slate-100{
|
7567
|
+
--tw-bg-opacity:1;
|
7568
|
+
background-color:rgb(241 245 249 / var(--tw-bg-opacity))
|
7569
|
+
}
|
7570
|
+
|
7564
7571
|
.bg-opacity-25{
|
7565
7572
|
--tw-bg-opacity:0.25
|
7566
7573
|
}
|
@@ -7601,6 +7608,10 @@ trix-toolbar .trix-button-group:not(:first-child){
|
|
7601
7608
|
padding:0.25rem
|
7602
7609
|
}
|
7603
7610
|
|
7611
|
+
.p-1\.5{
|
7612
|
+
padding:0.375rem
|
7613
|
+
}
|
7614
|
+
|
7604
7615
|
.px-1{
|
7605
7616
|
padding-left:0.25rem;
|
7606
7617
|
padding-right:0.25rem
|
@@ -9702,10 +9713,6 @@ trix-editor {
|
|
9702
9713
|
grid-template-columns:repeat(4, minmax(0, 1fr))
|
9703
9714
|
}
|
9704
9715
|
|
9705
|
-
.xl\:grid-cols-3{
|
9706
|
-
grid-template-columns:repeat(3, minmax(0, 1fr))
|
9707
|
-
}
|
9708
|
-
|
9709
9716
|
.xl\:flex-row{
|
9710
9717
|
flex-direction:row
|
9711
9718
|
}
|
@@ -9764,8 +9771,4 @@ trix-editor {
|
|
9764
9771
|
.\32xl\:grid-cols-6{
|
9765
9772
|
grid-template-columns:repeat(6, minmax(0, 1fr))
|
9766
9773
|
}
|
9767
|
-
|
9768
|
-
.\32xl\:grid-cols-4{
|
9769
|
-
grid-template-columns:repeat(4, minmax(0, 1fr))
|
9770
|
-
}
|
9771
9774
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.31.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrian Marin
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-04-
|
12
|
+
date: 2023-04-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -101,14 +101,14 @@ dependencies:
|
|
101
101
|
requirements:
|
102
102
|
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
104
|
+
version: 2.54.0
|
105
105
|
type: :runtime
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version:
|
111
|
+
version: 2.54.0
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: turbo-rails
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1371,8 +1371,14 @@ files:
|
|
1371
1371
|
- app/components/avo/fields/common/boolean_check_component.rb
|
1372
1372
|
- app/components/avo/fields/common/boolean_group_component.html.erb
|
1373
1373
|
- app/components/avo/fields/common/boolean_group_component.rb
|
1374
|
-
- app/components/avo/fields/common/
|
1375
|
-
- app/components/avo/fields/common/
|
1374
|
+
- app/components/avo/fields/common/files/controls_component.html.erb
|
1375
|
+
- app/components/avo/fields/common/files/controls_component.rb
|
1376
|
+
- app/components/avo/fields/common/files/list_viewer_component.html.erb
|
1377
|
+
- app/components/avo/fields/common/files/list_viewer_component.rb
|
1378
|
+
- app/components/avo/fields/common/files/view_type/grid_component.html.erb
|
1379
|
+
- app/components/avo/fields/common/files/view_type/grid_component.rb
|
1380
|
+
- app/components/avo/fields/common/files/view_type/list_component.html.erb
|
1381
|
+
- app/components/avo/fields/common/files/view_type/list_component.rb
|
1376
1382
|
- app/components/avo/fields/common/gravatar_viewer_component.html.erb
|
1377
1383
|
- app/components/avo/fields/common/gravatar_viewer_component.rb
|
1378
1384
|
- app/components/avo/fields/common/heading_component.html.erb
|
@@ -1381,8 +1387,6 @@ files:
|
|
1381
1387
|
- app/components/avo/fields/common/key_value_component.rb
|
1382
1388
|
- app/components/avo/fields/common/progress_bar_component.html.erb
|
1383
1389
|
- app/components/avo/fields/common/progress_bar_component.rb
|
1384
|
-
- app/components/avo/fields/common/single_file_viewer_component.html.erb
|
1385
|
-
- app/components/avo/fields/common/single_file_viewer_component.rb
|
1386
1390
|
- app/components/avo/fields/common/status_viewer_component.html.erb
|
1387
1391
|
- app/components/avo/fields/common/status_viewer_component.rb
|
1388
1392
|
- app/components/avo/fields/concerns/item_labels.rb
|
@@ -1642,6 +1646,7 @@ files:
|
|
1642
1646
|
- app/views/avo/actions/keep_modal_open.turbo_stream.erb
|
1643
1647
|
- app/views/avo/actions/show.html.erb
|
1644
1648
|
- app/views/avo/associations/new.html.erb
|
1649
|
+
- app/views/avo/attachments/destroy.turbo_stream.erb
|
1645
1650
|
- app/views/avo/base/_boolean_filter.html.erb
|
1646
1651
|
- app/views/avo/base/_multiple_select_filter.html.erb
|
1647
1652
|
- app/views/avo/base/_select_filter.html.erb
|
@@ -1721,6 +1726,7 @@ files:
|
|
1721
1726
|
- lib/avo/concerns/has_stimulus_controllers.rb
|
1722
1727
|
- lib/avo/concerns/is_resource_item.rb
|
1723
1728
|
- lib/avo/concerns/model_class_constantized.rb
|
1729
|
+
- lib/avo/concerns/policy_helpers.rb
|
1724
1730
|
- lib/avo/concerns/visible_in_dashboard.rb
|
1725
1731
|
- lib/avo/concerns/visible_items.rb
|
1726
1732
|
- lib/avo/configuration.rb
|
@@ -1,5 +0,0 @@
|
|
1
|
-
<div class="relative py-3 grid xs:grid-cols-2 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 rounded-xl">
|
2
|
-
<% @field.value.attachments.each do |file| %>
|
3
|
-
<%= render Avo::Fields::Common::SingleFileViewerComponent.new field: @field, resource: @resource, file: file %>
|
4
|
-
<% end %>
|
5
|
-
</div>
|
@@ -1,57 +0,0 @@
|
|
1
|
-
<div class="relative min-h-full max-w-full flex-1 flex flex-col justify-between space-y-3">
|
2
|
-
<% if file.present? %>
|
3
|
-
<div class="flex flex-col justify-between h-full">
|
4
|
-
<% if file.representable? && is_image? %>
|
5
|
-
<div class="max-h-[42rem] h-full flex">
|
6
|
-
<%= image_tag helpers.main_app.url_for(file), class: 'rounded-lg object-cover' %>
|
7
|
-
</div>
|
8
|
-
<% elsif is_audio? %>
|
9
|
-
<%= audio_tag(helpers.main_app.url_for(file), controls: true, preload: false, class: 'w-full') %>
|
10
|
-
<% elsif is_video? %>
|
11
|
-
<%= video_tag(helpers.main_app.url_for(file), controls: true, preload: false, class: 'w-full') %>
|
12
|
-
<% else %>
|
13
|
-
<div class="relative flex flex-col justify-evenly items-center px-2 rounded-lg border bg-white border-gray-500 min-h-24">
|
14
|
-
<div class="flex flex-col justify-center items-center w-full">
|
15
|
-
<%= helpers.svg 'document-text', class: 'h-10 text-gray-600 mb-2' %>
|
16
|
-
</div>
|
17
|
-
</div>
|
18
|
-
<% end %>
|
19
|
-
<% if field.display_filename %>
|
20
|
-
<span class="text-gray-500 mt-2 text-sm truncate" title="<%= file.filename %>"><%= file.filename %></span>
|
21
|
-
<% end %>
|
22
|
-
</div>
|
23
|
-
<div class="flex space-x-2">
|
24
|
-
<div class="flex">
|
25
|
-
<% if can_download_file? %>
|
26
|
-
<%= a_link Rails.application.routes.url_helpers.rails_blob_path(file, only_path: true, disposition: :attachment),
|
27
|
-
icon: 'heroicons/outline/download',
|
28
|
-
color: :primary,
|
29
|
-
download: true,
|
30
|
-
class: 'text-center',
|
31
|
-
title: t('avo.download_file'),
|
32
|
-
data: { tippy: :tooltip },
|
33
|
-
compact: true,
|
34
|
-
size: :xs %>
|
35
|
-
<% end %>
|
36
|
-
</div>
|
37
|
-
<div>
|
38
|
-
<% if can_delete_file? %>
|
39
|
-
<%= a_link destroy_path,
|
40
|
-
icon: 'heroicons/outline/trash',
|
41
|
-
color: :red,
|
42
|
-
compact: true,
|
43
|
-
size: :xs,
|
44
|
-
class: 'text-center',
|
45
|
-
title: t('avo.delete_file', item: file.filename),
|
46
|
-
data: {
|
47
|
-
turbo_method: :delete,
|
48
|
-
turbo_confirm: t('avo.are_you_sure'),
|
49
|
-
tippy: :tooltip
|
50
|
-
} %>
|
51
|
-
<% end %>
|
52
|
-
</div>
|
53
|
-
</div>
|
54
|
-
<% else %>
|
55
|
-
–
|
56
|
-
<% end %>
|
57
|
-
</div>
|