avo 2.5.2.pre.4 → 2.5.2.pre.7

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.

Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +4 -1
  4. data/app/assets/builds/avo.css +764 -166
  5. data/app/assets/builds/avo.js +212 -123
  6. data/app/assets/builds/avo.js.map +3 -3
  7. data/app/assets/stylesheets/avo.css +3 -33
  8. data/app/assets/stylesheets/css/alerts.css +35 -0
  9. data/app/assets/stylesheets/css/search.css +1 -1
  10. data/app/assets/stylesheets/css/tags.css +16 -0
  11. data/app/assets/svgs/heroicons/solid/user-remove.svg +1 -1
  12. data/app/components/avo/actions_component.html.erb +1 -2
  13. data/app/components/avo/alert_component.html.erb +1 -1
  14. data/app/components/avo/alert_component.rb +5 -24
  15. data/app/components/avo/button_component.rb +0 -2
  16. data/app/components/avo/fields/tags_field/edit_component.html.erb +27 -0
  17. data/app/components/avo/fields/tags_field/edit_component.rb +4 -0
  18. data/app/components/avo/fields/tags_field/index_component.html.erb +14 -0
  19. data/app/components/avo/fields/tags_field/index_component.rb +7 -0
  20. data/app/components/avo/fields/tags_field/show_component.html.erb +7 -0
  21. data/app/components/avo/fields/tags_field/show_component.rb +11 -0
  22. data/app/components/avo/fields/tags_field/tag_component.html.erb +9 -0
  23. data/app/components/avo/fields/tags_field/tag_component.rb +11 -0
  24. data/app/components/avo/filters_component.html.erb +1 -1
  25. data/app/components/avo/index/field_wrapper_component.html.erb +1 -1
  26. data/app/components/avo/index/grid_cover_empty_state_component.html.erb +1 -1
  27. data/app/components/avo/index/resource_table_component.html.erb +1 -1
  28. data/app/components/avo/panel_component.html.erb +3 -3
  29. data/app/components/avo/panel_component.rb +1 -1
  30. data/app/components/avo/resource_component.rb +0 -50
  31. data/app/components/avo/sidebar/heading_component.html.erb +1 -1
  32. data/app/components/avo/sidebar/link_component.rb +1 -1
  33. data/app/components/avo/sidebar_component.html.erb +13 -5
  34. data/app/components/avo/sidebar_profile_component.html.erb +1 -1
  35. data/app/components/avo/views/resource_edit_component.html.erb +3 -28
  36. data/app/components/avo/views/resource_edit_component.rb +6 -4
  37. data/app/components/avo/views/resource_index_component.html.erb +7 -15
  38. data/app/components/avo/views/resource_new_component.html.erb +2 -8
  39. data/app/components/avo/views/resource_show_component.html.erb +5 -15
  40. data/app/components/avo/views/resource_show_component.rb +45 -0
  41. data/app/controllers/avo/actions_controller.rb +8 -23
  42. data/app/controllers/avo/associations_controller.rb +3 -3
  43. data/app/controllers/avo/base_controller.rb +16 -25
  44. data/app/controllers/avo/search_controller.rb +2 -2
  45. data/app/helpers/avo/application_helper.rb +1 -1
  46. data/app/javascript/js/application.js +1 -1
  47. data/app/javascript/js/controllers/alerts_controller.js +26 -0
  48. data/app/javascript/js/controllers/base_controller.js +22 -0
  49. data/app/javascript/js/controllers/fields/key_value_controller.js +1 -1
  50. data/app/javascript/js/controllers/fields/tags_field_controller.js +86 -0
  51. data/app/javascript/js/controllers/fields/tags_field_helpers.js +47 -0
  52. data/app/javascript/js/controllers/filter_controller.js +1 -4
  53. data/app/javascript/js/controllers.js +4 -0
  54. data/app/views/avo/actions/show.html.erb +2 -5
  55. data/app/views/avo/partials/_logo.html.erb +1 -1
  56. data/app/views/avo/partials/_navbar.html.erb +6 -12
  57. data/app/views/avo/private/_links_and_buttons.html.erb +1 -1
  58. data/app/views/layouts/avo/application.html.erb +53 -50
  59. data/db/factories.rb +2 -0
  60. data/lib/avo/base_action.rb +6 -24
  61. data/lib/avo/base_resource.rb +6 -0
  62. data/lib/avo/concerns/handles_field_args.rb +36 -0
  63. data/lib/avo/engine.rb +1 -1
  64. data/lib/avo/fields/base_field.rb +2 -1
  65. data/lib/avo/fields/belongs_to_field.rb +4 -4
  66. data/lib/avo/fields/has_and_belongs_to_many_field.rb +2 -2
  67. data/lib/avo/fields/has_base_field.rb +0 -2
  68. data/lib/avo/fields/has_many_field.rb +2 -2
  69. data/lib/avo/fields/has_one_field.rb +2 -2
  70. data/lib/avo/fields/tags_field.rb +82 -0
  71. data/lib/avo/hosts/record_host.rb +7 -0
  72. data/lib/avo/licensing/pro_license.rb +2 -1
  73. data/lib/avo/version.rb +1 -1
  74. data/lib/generators/avo/templates/locales/avo.en.yml +4 -0
  75. data/public/avo-assets/avo.css +812 -214
  76. data/public/avo-assets/avo.js +212 -123
  77. data/public/avo-assets/avo.js.map +3 -3
  78. metadata +19 -2
@@ -4,6 +4,7 @@
4
4
  @import './../../../node_modules/trix/dist/trix.css';
5
5
  @import './../../../node_modules/flatpickr/dist/flatpickr.css';
6
6
  @import './../../../node_modules/@algolia/autocomplete-theme-classic/dist/theme.css';
7
+ @import './../../../node_modules/@yaireo/tagify/dist/tagify.css';
7
8
 
8
9
  @import 'tailwindcss/base';
9
10
 
@@ -11,12 +12,14 @@
11
12
  @import './css/buttons.css';
12
13
  @import './css/typography.css';
13
14
  @import './css/tooltips.css';
15
+ @import './css/alerts.css';
14
16
  @import './css/loader.css';
15
17
  @import './css/pagination.css';
16
18
  @import './css/breadcrumbs.css';
17
19
  @import './css/search.css';
18
20
  @import './css/active-storage.css';
19
21
  @import './css/spinner.css';
22
+ @import './css/tags.css';
20
23
 
21
24
  @import './css/components/status.css';
22
25
  @import './css/components/code.css';
@@ -88,36 +91,3 @@ trix-editor {
88
91
  max-height: 320px !important;
89
92
  overflow-y: auto;
90
93
  }
91
-
92
- .scroll-shadows {
93
- background:
94
- /* Shadow Cover TOP */
95
- linear-gradient(
96
- #F6F6F7 30%,
97
- #F6F6F7
98
- ) center top,
99
-
100
- /* Shadow Cover BOTTOM */
101
- linear-gradient(
102
- #F6F6F7,
103
- #F6F6F7 70%
104
- ) center bottom,
105
-
106
- /* Shadow TOP */
107
- radial-gradient(
108
- farthest-side at 50% 0,
109
- rgba(0, 0, 0, 0.2),
110
- rgba(0, 0, 0, 0)
111
- ) center top,
112
-
113
- /* Shadow BOTTOM */
114
- radial-gradient(
115
- farthest-side at 50% 100%,
116
- rgba(0, 0, 0, 0.2),
117
- rgba(0, 0, 0, 0)
118
- ) center bottom;
119
-
120
- background-repeat: no-repeat;
121
- background-size: 100% 34px, 100% 34px, 100% 14px, 100% 14px;
122
- background-attachment: local, local, scroll, scroll;
123
- }
@@ -0,0 +1,35 @@
1
+ #toast-container > div {
2
+ box-shadow: none;
3
+ background-size: 1.5rem;
4
+ background-position: 0.8rem 0.8rem;
5
+ width: 500px;
6
+
7
+ @apply shadow-md opacity-100 border border-gray-200 rounded-md pt-3 pr-3 pb-3 bg-white;
8
+
9
+ &:hover {
10
+ @apply shadow-xl;
11
+ }
12
+
13
+ .toast-title {
14
+ @apply text-gray-800;
15
+ }
16
+ .toast-message {
17
+ @apply text-gray-800;
18
+ }
19
+
20
+ &.toast-success {
21
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0iIzM4YTE2OSI+CiAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNi4yNjcgMy40NTVhMy4wNjYgMy4wNjYgMCAwMDEuNzQ1LS43MjMgMy4wNjYgMy4wNjYgMCAwMTMuOTc2IDAgMy4wNjYgMy4wNjYgMCAwMDEuNzQ1LjcyMyAzLjA2NiAzLjA2NiAwIDAxMi44MTIgMi44MTJjLjA1MS42NDMuMzA0IDEuMjU0LjcyMyAxLjc0NWEzLjA2NiAzLjA2NiAwIDAxMCAzLjk3NiAzLjA2NiAzLjA2NiAwIDAwLS43MjMgMS43NDUgMy4wNjYgMy4wNjYgMCAwMS0yLjgxMiAyLjgxMiAzLjA2NiAzLjA2NiAwIDAwLTEuNzQ1LjcyMyAzLjA2NiAzLjA2NiAwIDAxLTMuOTc2IDAgMy4wNjYgMy4wNjYgMCAwMC0xLjc0NS0uNzIzIDMuMDY2IDMuMDY2IDAgMDEtMi44MTItMi44MTIgMy4wNjYgMy4wNjYgMCAwMC0uNzIzLTEuNzQ1IDMuMDY2IDMuMDY2IDAgMDEwLTMuOTc2IDMuMDY2IDMuMDY2IDAgMDAuNzIzLTEuNzQ1IDMuMDY2IDMuMDY2IDAgMDEyLjgxMi0yLjgxMnptNy40NCA1LjI1MmExIDEgMCAwMC0xLjQxNC0xLjQxNEw5IDEwLjU4NiA3LjcwNyA5LjI5M2ExIDEgMCAwMC0xLjQxNCAxLjQxNGwyIDJhMSAxIDAgMDAxLjQxNCAwbDQtNHoiIGNsaXAtcnVsZT0iZXZlbm9kZCIgLz4KPC9zdmc+Cg==) !important;
22
+ }
23
+
24
+ &.toast-warning {
25
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0icmdiYSgyMTcsIDExOSwgNiwgMSkiPgogIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTguMjU3IDMuMDk5Yy43NjUtMS4zNiAyLjcyMi0xLjM2IDMuNDg2IDBsNS41OCA5LjkyYy43NSAxLjMzNC0uMjEzIDIuOTgtMS43NDIgMi45OEg0LjQyYy0xLjUzIDAtMi40OTMtMS42NDYtMS43NDMtMi45OGw1LjU4LTkuOTJ6TTExIDEzYTEgMSAwIDExLTIgMCAxIDEgMCAwMTIgMHptLTEtOGExIDEgMCAwMC0xIDF2M2ExIDEgMCAwMDIgMFY2YTEgMSAwIDAwLTEtMXoiIGNsaXAtcnVsZT0iZXZlbm9kZCIgLz4KPC9zdmc+Cg==) !important;
26
+ }
27
+
28
+ &.toast-info {
29
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0icmdiYSgzNywgOTksIDIzNSwgMSkiPgogIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTE4IDEwYTggOCAwIDExLTE2IDAgOCA4IDAgMDExNiAwem0tNy00YTEgMSAwIDExLTIgMCAxIDEgMCAwMTIgMHpNOSA5YTEgMSAwIDAwMCAydjNhMSAxIDAgMDAxIDFoMWExIDEgMCAxMDAtMnYtM2ExIDEgMCAwMC0xLTFIOXoiIGNsaXAtcnVsZT0iZXZlbm9kZCIgLz4KPC9zdmc+Cg==) !important;
30
+ }
31
+
32
+ &.toast-error {
33
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0icmdiYSgyMjAsIDM4LCAzOCwgMSkiPgogIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTE4IDEwYTggOCAwIDExLTE2IDAgOCA4IDAgMDExNiAwem0tNyA0YTEgMSAwIDExLTIgMCAxIDEgMCAwMTIgMHptLTEtOWExIDEgMCAwMC0xIDF2NGExIDEgMCAxMDIgMFY2YTEgMSAwIDAwLTEtMXoiIGNsaXAtcnVsZT0iZXZlbm9kZCIgLz4KPC9zdmc+Cg==) !important;
34
+ }
35
+ }
@@ -32,7 +32,7 @@
32
32
 
33
33
  .aa-DetachedFormContainer,
34
34
  .aa-DetachedContainer .aa-Panel {
35
- @apply bg-gray-50 border-b-0;
35
+ @apply bg-gray-100 border-b-0;
36
36
  }
37
37
 
38
38
  .aa-Form {
@@ -0,0 +1,16 @@
1
+ tags.tagify {
2
+ --tag-inset-shadow-size: 3em;
3
+ }
4
+
5
+ tags.tagify {
6
+ @apply !p-0;
7
+
8
+ span.tagify__input {
9
+ @apply my-1;
10
+ }
11
+ }
12
+
13
+ tag.tagify__tag {
14
+ @apply text-sm my-1 mb-0;
15
+ }
16
+
@@ -1,3 +1,3 @@
1
- or<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
2
2
  <path d="M11 6a3 3 0 11-6 0 3 3 0 016 0zM14 17a6 6 0 00-12 0h12zM13 8a1 1 0 100 2h4a1 1 0 100-2h-4z"/>
3
3
  </svg>
@@ -3,8 +3,7 @@
3
3
  data-actions-picker-enabled-class="text-black hover:bg-blue-500 hover:text-white"
4
4
  data-actions-picker-disabled-class="cursor-wait text-gray-500"
5
5
  >
6
- <%= a_button style: :outline,
7
- color: :primary,
6
+ <%= a_button style: :primary,
8
7
  class: "focus:outline-none",
9
8
  icon: 'arrow-circle-right',
10
9
  icon_class: 'transform rotate-90',
@@ -13,7 +13,7 @@
13
13
  <%== message %>
14
14
  </p>
15
15
  </div>
16
- <div class="ml-4 flex-shrink-0 flex items-center">
16
+ <div class="ml-4 flex-shrink-0 flex">
17
17
  <button data-action="alert#close" class="inline-flex text-white focus:outline-none focus:text-gray-300 transition ease-in-out duration-150">
18
18
  <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
19
19
  <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
@@ -12,10 +12,7 @@ class Avo::AlertComponent < ViewComponent::Base
12
12
  end
13
13
 
14
14
  def icon
15
- return "heroicons/solid/x-circle" if is_error?
16
- return "heroicons/solid/exclamation" if is_warning?
17
- return "heroicons/solid/exclamation-circle" if is_info?
18
- return "heroicons/solid/check-circle" if is_success?
15
+ return "x-circle" if is_error?
19
16
 
20
17
  "check-circle"
21
18
  end
@@ -24,31 +21,15 @@ class Avo::AlertComponent < ViewComponent::Base
24
21
  result = "max-w-lg w-full shadow-lg rounded px-4 py-3 rounded relative border text-white pointer-events-auto"
25
22
 
26
23
  result += if is_error?
27
- " bg-red-400 border-red-600"
28
- elsif is_success?
29
- " bg-green-500 border-green-600"
30
- elsif is_warning?
31
- " bg-orange-400 border-orange-600"
32
- elsif is_info?
33
- " bg-blue-400 border-blue-600"
24
+ " bg-red-400 border-red-700"
25
+ else
26
+ " bg-green-400 border-green-700"
34
27
  end
35
28
 
36
29
  result
37
30
  end
38
31
 
39
32
  def is_error?
40
- type.to_sym == :error || type.to_sym == :alert
41
- end
42
-
43
- def is_success?
44
- type.to_sym == :success
45
- end
46
-
47
- def is_info?
48
- type.to_sym == :notice || type.to_sym == :info
49
- end
50
-
51
- def is_warning?
52
- type.to_sym == :warning
33
+ type.to_sym == :error
53
34
  end
54
35
  end
@@ -117,8 +117,6 @@ class Avo::ButtonComponent < ViewComponent::Base
117
117
  " bg-primary-500 text-white border-primary-500 hover:bg-primary-600 hover:border-primary-600 active:border-primary-700 active:outline-primary-700 active:bg-primary-600"
118
118
  when :outline
119
119
  " bg-white text-#{@color}-500 border-#{@color}-500 hover:bg-#{@color}-100 active:bg-#{@color}-100 active:border-#{@color}-500 active:outline-#{@color}-500"
120
- when :text
121
- " text-#{@color}-500 active:outline-#{@color}-500 border-none hover:bg-gray-100"
122
120
  else
123
121
  ""
124
122
  end
@@ -0,0 +1,27 @@
1
+ <%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
2
+ <div data-controller="tags-field">
3
+ <%# dummy field %>
4
+ <%= text_field_tag "#{@field.id}-dummy", '',
5
+ class: helpers.input_classes('w-full', has_error: @field.model_errors.include?(@field.id)),
6
+ placeholder: @field.placeholder,
7
+ disabled: @field.readonly,
8
+ value: '',
9
+ data: {
10
+ 'tags-field-target': 'fakeInput',
11
+ } %>
12
+ <%# real field %>
13
+ <%= @form.text_field @field.id,
14
+ class: helpers.input_classes('hidden w-full', has_error: @field.model_errors.include?(@field.id)),
15
+ placeholder: @field.placeholder,
16
+ disabled: @field.readonly,
17
+ value: @field.field_value.to_json,
18
+ data: {
19
+ 'tags-field-target': 'input',
20
+ 'whitelist-items': @field.suggestions.to_json,
21
+ 'blacklist-items': @field.blacklist.to_json,
22
+ 'enforce-suggestions': @field.enforce_suggestions ? 1 : 0,
23
+ 'delimiters': @field.delimiters,
24
+ 'close-on-select': @field.close_on_select ? 1 : 0,
25
+ } %>
26
+ </div>
27
+ <% end %>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Avo::Fields::TagsField::EditComponent < Avo::Fields::EditComponent
4
+ end
@@ -0,0 +1,14 @@
1
+ <%= index_field_wrapper field: @field do %>
2
+ <div class="flex gap-1 items-center flex-nowrap">
3
+ <% value.take(3).each do |item| %>
4
+ <% if @field.acts_as_taggable_on.present? %>
5
+ <%= render Avo::Fields::TagsField::TagComponent.new(label: item['value']) %>
6
+ <% else %>
7
+ <%= render Avo::Fields::TagsField::TagComponent.new(label: item) %>
8
+ <% end %>
9
+ <% end %>
10
+ <% if value.count > 3 %>
11
+ <%= render Avo::Fields::TagsField::TagComponent.new(label: '...', title: I18n.t('avo.x_items_more', count: value.count - 3)) %>
12
+ <% end %>
13
+ </div>
14
+ <% end %>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Avo::Fields::TagsField::IndexComponent < Avo::Fields::IndexComponent
4
+ def value
5
+ @field.field_value
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ <%= show_field_wrapper field: @field, index: @index do %>
2
+ <div class="flex gap-1 items-center flex-wrap">
3
+ <% @field.field_value.each do |item| %>
4
+ <%= render Avo::Fields::TagsField::TagComponent.new(label: label_from_item(item)) %>
5
+ <% end %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Avo::Fields::TagsField::ShowComponent < Avo::Fields::ShowComponent
4
+ def label_from_item(item)
5
+ if @field.acts_as_taggable_on.present?
6
+ item['value']
7
+ else
8
+ item
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ <div class="flex px-2 py-1 rounded bg-gray-200 text-sm text-gray-800 font-normal flex-shrink-0"
2
+ <% if title.present? %>
3
+ data-tippy="tooltip"
4
+ title="<%= title %>"
5
+ <% end %>
6
+ data-target="tag-component"
7
+ >
8
+ <%= label %>
9
+ </div>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Avo::Fields::TagsField::TagComponent < ViewComponent::Base
4
+ attr_reader :label
5
+ attr_reader :title
6
+
7
+ def initialize(label: nil, title: nil)
8
+ @label = label
9
+ @title = title
10
+ end
11
+ end
@@ -14,7 +14,7 @@
14
14
  <% end %>
15
15
  <% end %>
16
16
  <div
17
- class="absolute block inset-auto sm:right-0 top-full bg-white min-w-[300px] mt-2 z-20 shadow-modal rounded divide-y divide-gray-300 <%= 'hidden' unless params[:keep_filters_panel_open] == '1' %>"
17
+ class="absolute block inset-auto sm:right-0 top-full bg-white min-w-[300px] mt-2 z-20 shadow-modal rounded divide-y divide-gray-300 <%= 'hidden' unless params[:keep_filters_panel_open] %>"
18
18
  data-toggle-panel-target="panel"
19
19
  >
20
20
  <% @filters.each do |filter| %>
@@ -1,4 +1,4 @@
1
- <td class="min-h-[3rem] px-3 leading-tight whitespace-nowrap h-full text-slate-800 text-sm <%= classes %>" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
1
+ <td class="min-h-[3rem] px-3 leading-tight whitespace-nowrap h-full text-slate-800 <%= classes %>" data-field-id="<%= @field.id %>" data-field-type="<%= @field.type %>">
2
2
  <% if @field.value.blank? && @dash_if_blank %>
3
3
 
4
4
  <% else %>
@@ -1,3 +1,3 @@
1
- <div class="absolute bg-gray-50 w-full h-full">
1
+ <div class="absolute bg-gray-100 w-full h-full">
2
2
  <%= 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' %>
3
3
  </div>
@@ -1,5 +1,5 @@
1
1
  <div class="w-full ">
2
- <table class="w-full px-4 bg-white rounded" data-resource-name='<%= @resource.model_key %>' data-controller='item-select-all'>
2
+ <table class="w-full px-4 bg-white" data-resource-name='<%= @resource.model_key %>' data-controller='item-select-all'>
3
3
  <%= render partial: 'avo/partials/table_header', locals: {fields: @resource.get_fields(reflection: @reflection)} %>
4
4
  <tbody class="divide-y">
5
5
  <% @resources.each_with_index do |resource, index| %>
@@ -1,7 +1,7 @@
1
1
  <div <%== data_attributes %>>
2
2
  <% if render_header? %>
3
- <div class="flex-1 flex flex-col xl:flex-row justify-between mb-4">
4
- <div class="overflow-hidden flex flex-col">
3
+ <div class="<%= white_panel_classes %> p-4 flex-1 flex flex-col xl:flex-row justify-between mb-6">
4
+ <div class="overflow-hidden mr-4 flex flex-col">
5
5
  <% if display_breadcrumbs? %>
6
6
  <div class="breadcrumbs truncate mb-2">
7
7
  <%= 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 %>
@@ -13,7 +13,7 @@
13
13
  </div>
14
14
 
15
15
  <% if description.present? %>
16
- <div class="text-sm tracking-normal font-medium text-gray-600" data-target="description">
16
+ <div class="text-base tracking-normal font-medium text-gray-600" data-target="description">
17
17
  <%== description %>
18
18
  </div>
19
19
  <% end %>
@@ -21,7 +21,7 @@ class Avo::PanelComponent < ViewComponent::Base
21
21
  private
22
22
 
23
23
  def white_panel_classes
24
- "bg-white rounded shadow"
24
+ 'bg-white rounded shadow'
25
25
  end
26
26
 
27
27
  def data_attributes
@@ -11,26 +11,6 @@ class Avo::ResourceComponent < Avo::BaseComponent
11
11
  @resource.authorization.authorize_action(:destroy, raise_exception: false)
12
12
  end
13
13
 
14
- def can_detach?
15
- authorize_association_for("detach")
16
- end
17
-
18
- def can_see_the_edit_button?
19
- @resource.authorization.authorize_action(:edit, raise_exception: false)
20
- end
21
-
22
- def can_see_the_destroy_button?
23
- @resource.authorization.authorize_action(:destroy, raise_exception: false)
24
- end
25
-
26
- def detach_path
27
- helpers.resource_detach_path(params[:resource_name], params[:id], @reflection.name.to_s, @resource.model.id)
28
- end
29
-
30
- def destroy_path
31
- helpers.resource_path(model: @resource.model, resource: @resource)
32
- end
33
-
34
14
  def authorize_association_for(policy_method)
35
15
  association_policy = true
36
16
 
@@ -50,34 +30,4 @@ class Avo::ResourceComponent < Avo::BaseComponent
50
30
 
51
31
  association_policy
52
32
  end
53
-
54
- def split_panel_fields
55
- initialize_panels
56
- @resource.get_fields.each do |field|
57
- case field.class.to_s
58
- when "Avo::Fields::HasOneField"
59
- @has_one_panels << field
60
- when "Avo::Fields::HasManyField"
61
- @has_many_panels << field
62
- when "Avo::Fields::HasAndBelongsToManyField"
63
- @has_as_belongs_to_many_panels << field
64
- else
65
- @fields_by_panel[field.panel_name] ||= []
66
- @fields_by_panel[field.panel_name] << field
67
- end
68
- end
69
- end
70
-
71
- private
72
-
73
- def initialize_panels
74
- @fields_by_panel = {}
75
- @has_one_panels = []
76
- @has_many_panels = []
77
- @has_as_belongs_to_many_panels = []
78
- end
79
-
80
- def via_resource?
81
- params[:via_resource_class].present? && params[:via_resource_id].present?
82
- end
83
33
  end
@@ -1,4 +1,4 @@
1
- <div class="flex justify-between px-6 py-2 text-gray-500">
1
+ <div class="flex justify-between p-4 py-2 text-gray-500">
2
2
  <div class="flex items-center text-sm uppercase font-semibold leading-none space-x-1">
3
3
  <span class="min-w-[20px]"><%= icon %></span> <span><%= label %></span>
4
4
  </div>
@@ -23,6 +23,6 @@ class Avo::Sidebar::LinkComponent < ViewComponent::Base
23
23
  end
24
24
 
25
25
  def classes
26
- "px-4 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100"
26
+ "px-4 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-150"
27
27
  end
28
28
  end
@@ -1,16 +1,24 @@
1
1
  <div
2
- class="fixed z-[60] t-0 application-sidebar hidden lg:flex flex-1 border-r lg:border-none bg-none min-w-[16rem] h-[calc(100vh-4rem)] bg-gray-50 lg:bg-transparent <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
2
+ class="fixed z-[60] application-sidebar hidden lg:flex h-full bg-white text-white w-64 border-r <%= 'print:hidden' if Avo.configuration.hide_layout_when_printing %>"
3
3
  data-mobile-target="sidebar"
4
4
  >
5
5
  <div class="flex flex-col w-full h-full">
6
- <div class="flex-1 flex flex-col justify-between overflow-auto h-full pt-3 scroll-shadows">
6
+ <div class="flex justify-between">
7
+ <%= render partial: "avo/partials/logo" %>
8
+ <div class="flex items-center mr-4">
9
+ <%= helpers.a_button class: "lg:hidden", icon: 'menu-back', data: { action: 'click->mobile#toggleSidebar' } %>
10
+ </div>
11
+ </div>
12
+ <div class="flex-1 flex flex-col justify-between overflow-auto mt-3">
7
13
  <div class="space-y-6 mb-4">
8
14
  <%= render Avo::Sidebar::LinkComponent.new label: 'Get started', path: helpers.avo.root_path, active: :exclusive if Rails.env.development? && Avo.configuration.home_path.nil? %>
9
15
 
10
16
  <% if Avo::App.has_main_menu? %>
11
- <% Avo::App.main_menu.items.each do |item| %>
12
- <%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
13
- <% end %>
17
+ <div class="text-black">
18
+ <% Avo::App.main_menu.items.each do |item| %>
19
+ <%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
20
+ <% end %>
21
+ </div>
14
22
  <% else %>
15
23
 
16
24
  <% if dashboards.present? %>
@@ -1,4 +1,4 @@
1
- <div class="text-black Xborder-t border-gray-200 p-4 flex">
1
+ <div class="text-black border-t border-gray-200 p-4 flex">
2
2
  <div class="flex-1 flex space-x-4">
3
3
  <% if avatar.present? %>
4
4
  <div class="relative aspect-square w-10 h-10 overflow-hidden rounded">
@@ -1,6 +1,4 @@
1
- <div data-model-id="<%= @resource.model.id %>"
2
- class="space-y-8"
3
- >
1
+ <div data-model-id="<%= @resource.model.id %>">
4
2
  <% @resource.panels.each do |resource_panel| %>
5
3
  <%= form_with model: @resource.model,
6
4
  scope: @resource.form_scope,
@@ -11,17 +9,11 @@
11
9
  <%= render Avo::ReferrerParamsComponent.new back_path: back_path %>
12
10
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], description: @resource.resource_description, display_breadcrumbs: true) do |c| %>
13
11
  <% c.tools do %>
14
- <%= a_link back_path,
15
- style: :text,
16
- icon: 'arrow-left' do %>
12
+ <%= a_link back_path, icon: 'arrow-left' do %>
17
13
  <%= t('avo.cancel').capitalize %>
18
14
  <% end %>
19
15
  <% if can_see_the_save_button? %>
20
- <%= a_button color: :primary,
21
- style: :primary,
22
- loading: true,
23
- type: :submit,
24
- icon: 'save' do %>
16
+ <%= a_button color: :green, loading: true, type: :submit, icon: 'save' do %>
25
17
  <%= t('avo.save').capitalize %>
26
18
  <% end %>
27
19
  <% end %>
@@ -48,21 +40,4 @@
48
40
  <% end %>
49
41
  <% end %>
50
42
  <% end %>
51
- <% if @reflection.blank? %>
52
- <% if has_one_panels.present? %>
53
- <% has_one_panels.each_with_index do |field, index| %>
54
- <%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
55
- <% end %>
56
- <% end %>
57
- <% if has_many_panels.present? %>
58
- <% has_many_panels.each_with_index do |field, index| %>
59
- <%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
60
- <% end %>
61
- <% end %>
62
- <% if has_as_belongs_to_many_panels.present? %>
63
- <% has_as_belongs_to_many_panels.each_with_index do |field, index| %>
64
- <%= render field.component_for_view(:show).new(field: field, resource: @resource, index: index) %>
65
- <% end %>
66
- <% end %>
67
- <% end %>
68
43
  </div>
@@ -4,12 +4,8 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
4
4
  include Avo::ResourcesHelper
5
5
  include Avo::ApplicationHelper
6
6
 
7
- attr_reader :fields_by_panel, :has_one_panels, :has_many_panels, :has_as_belongs_to_many_panels
8
-
9
7
  def initialize(resource: nil)
10
8
  @resource = resource
11
-
12
- split_panel_fields
13
9
  end
14
10
 
15
11
  def back_path
@@ -25,4 +21,10 @@ class Avo::Views::ResourceEditComponent < Avo::ResourceComponent
25
21
  def can_see_the_save_button?
26
22
  @resource.authorization.authorize_action :edit, raise_exception: false
27
23
  end
24
+
25
+ private
26
+
27
+ def via_resource?
28
+ params[:via_resource_class].present? && params[:via_resource_id].present?
29
+ end
28
30
  end
@@ -1,28 +1,19 @@
1
1
  <div>
2
2
  <%= render Avo::PanelComponent.new(title: title, description: description, data: { component: 'resources-index' }, display_breadcrumbs: @reflection.blank?) do |c| %>
3
3
  <% c.tools do %>
4
- <% if can_attach? %>
5
- <%= a_link attach_path,
6
- icon: 'heroicons/outline/link',
7
- color: :primary,
8
- style: :text,
9
- 'data-turbo-frame': 'attach_modal',
10
- 'data-target': 'attach' do %>
11
- <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
12
- <% end %>
13
- <% end %>
14
4
  <% if can_see_the_actions_button? %>
15
5
  <%= render Avo::ActionsComponent.new actions: @actions, resource: @resource %>
16
6
  <% end %>
17
7
  <% if can_see_the_create_button? %>
18
- <%= a_link create_path,
19
- icon: 'heroicons/outline/plus',
20
- 'data-target': 'create',
21
- style: :primary,
22
- color: :primary do %>
8
+ <%= a_link create_path, icon: 'heroicons/outline/plus', 'data-target': 'create', color: :primary do %>
23
9
  <%= t('avo.create_new_item', item: singular_resource_name.downcase ) %>
24
10
  <% end %>
25
11
  <% end %>
12
+ <% if can_attach? %>
13
+ <%= a_link attach_path, icon: 'heroicons/outline/link', color: :primary, 'data-turbo-frame': 'attach_modal', 'data-target': 'attach' do %>
14
+ <%= t('avo.attach_item', item: singular_resource_name).capitalize %>
15
+ <% end %>
16
+ <% end %>
26
17
  <% end %>
27
18
  <% c.body do %>
28
19
  <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 %>"
@@ -64,6 +55,7 @@
64
55
  </div>
65
56
  <% end %>
66
57
  <% end %>
58
+
67
59
  <% if view_type.to_sym == :grid %>
68
60
  <%= render Avo::Index::ResourceGridComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model) %>
69
61
  <div class="mt-14">
@@ -14,17 +14,11 @@
14
14
  <%= render Avo::PanelComponent.new(title: resource_panel[:name], description: @resource.resource_description, display_breadcrumbs: true) do |c| %>
15
15
  <% c.tools do %>
16
16
  <div class="flex justify-end space-x-2">
17
- <%= a_link back_path,
18
- style: :text,
19
- icon: 'arrow-left' do %>
17
+ <%= a_link back_path, icon: 'arrow-left' do %>
20
18
  <%= t('avo.cancel').capitalize %>
21
19
  <% end %>
22
20
  <% if can_see_the_save_button? %>
23
- <%= a_button color: :primary,
24
- style: :primary,
25
- loading: true,
26
- type: :submit,
27
- icon: 'save' do %>
21
+ <%= a_button color: 'green', loading: true, type: :submit, icon: 'save' do %>
28
22
  <%= t('avo.save').capitalize %>
29
23
  <% end %>
30
24
  <% end %>