avo 2.13.6.pre.2 → 2.14.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.

Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -3
  3. data/README.md +7 -11
  4. data/app/components/avo/button_component.rb +1 -1
  5. data/app/components/avo/fields/common/progress_bar_component.html.erb +8 -0
  6. data/app/components/avo/fields/common/progress_bar_component.rb +15 -0
  7. data/app/components/avo/fields/common/single_file_viewer_component.html.erb +1 -2
  8. data/app/components/avo/fields/common/single_file_viewer_component.rb +12 -0
  9. data/app/components/avo/fields/progress_bar_field/index_component.html.erb +1 -6
  10. data/app/components/avo/fields/progress_bar_field/show_component.html.erb +1 -6
  11. data/app/components/avo/filters_component.html.erb +1 -1
  12. data/app/components/avo/filters_component.rb +11 -1
  13. data/app/components/avo/index/resource_table_component.html.erb +37 -2
  14. data/app/components/avo/index/resource_table_component.rb +15 -1
  15. data/app/components/avo/item_switcher_component.rb +1 -1
  16. data/app/components/avo/tab_group_component.html.erb +4 -4
  17. data/app/components/avo/tab_group_component.rb +7 -1
  18. data/app/components/avo/tab_switcher_component.html.erb +28 -8
  19. data/app/components/avo/tab_switcher_component.rb +3 -1
  20. data/app/components/avo/views/resource_index_component.html.erb +3 -6
  21. data/app/components/avo/views/resource_index_component.rb +3 -2
  22. data/app/controllers/avo/actions_controller.rb +17 -4
  23. data/app/helpers/avo/resources_helper.rb +1 -1
  24. data/app/javascript/js/controllers/action_controller.js +11 -2
  25. data/app/javascript/js/controllers/item_select_all_controller.js +42 -4
  26. data/app/javascript/js/controllers/tabs_controller.js +13 -9
  27. data/app/views/avo/actions/show.html.erb +2 -1
  28. data/app/views/avo/base/index.html.erb +1 -0
  29. data/app/views/avo/partials/_table_header.html.erb +1 -1
  30. data/app/views/avo/partials/_view_toggle_button.html.erb +2 -2
  31. data/lib/avo/concerns/has_fields.rb +2 -2
  32. data/lib/avo/configuration.rb +2 -0
  33. data/lib/avo/fields/base_field.rb +1 -1
  34. data/lib/avo/fields/concerns/is_required.rb +15 -1
  35. data/lib/avo/services/encryption_service.rb +47 -0
  36. data/lib/avo/tab_group.rb +3 -1
  37. data/lib/avo/tab_group_builder.rb +4 -4
  38. data/lib/avo/version.rb +1 -1
  39. data/lib/generators/avo/templates/initializer/avo.tt +1 -0
  40. data/lib/generators/avo/templates/locales/avo.en.yml +5 -1
  41. data/lib/generators/avo/templates/locales/avo.fr.yml +4 -0
  42. data/lib/generators/avo/templates/locales/avo.nb-NO.yml +5 -0
  43. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +5 -0
  44. data/lib/generators/avo/templates/locales/avo.ro.yml +6 -0
  45. data/public/avo-assets/avo.css +44 -4
  46. data/public/avo-assets/avo.js +43 -43
  47. data/public/avo-assets/avo.js.map +2 -2
  48. metadata +7 -5
  49. data/app/views/avo/partials/_tabs_toggle.html.erb +0 -20
@@ -3,7 +3,7 @@ import { Controller } from '@hotwired/stimulus'
3
3
  import { castBoolean } from '../helpers/cast_boolean'
4
4
 
5
5
  export default class extends Controller {
6
- static targets = ['tab'];
6
+ static targets = ['tabPanel'];
7
7
 
8
8
  static values = {
9
9
  view: String,
@@ -11,13 +11,17 @@ export default class extends Controller {
11
11
  };
12
12
 
13
13
  get currentTab() {
14
- return this.tabTargets.find(
14
+ return this.tabPanelTargets.find(
15
15
  (element) => element.dataset.tabId === this.activeTabValue,
16
16
  )
17
17
  }
18
18
 
19
19
  targetTab(id) {
20
- return this.tabTargets.find((element) => element.dataset.tabId === id)
20
+ return this.tabTargets.find((element) => element.dataset.tabsIdParam === id)
21
+ }
22
+
23
+ targetTabPanel(id) {
24
+ return this.tabPanelTargets.find((element) => element.dataset.tabId === id)
21
25
  }
22
26
 
23
27
  changeTab(e) {
@@ -46,17 +50,17 @@ export default class extends Controller {
46
50
  }
47
51
 
48
52
  // We don't need to add a height to this panel because it was loaded before
49
- if (castBoolean(this.targetTab(id).dataset.loaded)) {
53
+ if (castBoolean(this.targetTabPanel(id).dataset.loaded)) {
50
54
  return
51
55
  }
52
56
 
53
57
  // Get the height of the active panel
54
58
  const { height } = this.currentTab.getBoundingClientRect()
55
59
  // Set it to the target panel
56
- this.targetTab(id).style.height = `${height}px`
60
+ this.targetTabPanel(id).style.height = `${height}px`
57
61
 
58
62
  // Wait until the panel loaded it's content and then remove the forced height
59
- const observer = new AttributeObserver(this.targetTab(id), 'busy', {
63
+ const observer = new AttributeObserver(this.targetTabPanel(id), 'busy', {
60
64
  elementUnmatchedAttribute: () => {
61
65
  // The content is not available in an instant so delay the height reset a bit.
62
66
  setTimeout(() => {
@@ -69,11 +73,11 @@ export default class extends Controller {
69
73
  }
70
74
 
71
75
  markTabLoaded(id) {
72
- this.targetTab(id).dataset.loaded = true
76
+ this.targetTabPanel(id).dataset.loaded = true
73
77
  }
74
78
 
75
79
  showTab(id) {
76
- this.tabTargets.forEach((element) => {
80
+ this.tabPanelTargets.forEach((element) => {
77
81
  if (element.dataset.tabId === id) {
78
82
  element.classList.remove('hidden')
79
83
  }
@@ -81,6 +85,6 @@ export default class extends Controller {
81
85
  }
82
86
 
83
87
  hideTabs() {
84
- this.tabTargets.map((element) => element.classList.add('hidden'))
88
+ this.tabPanelTargets.map((element) => element.classList.add('hidden'))
85
89
  }
86
90
  }
@@ -20,7 +20,8 @@
20
20
  <div class="flex-1 flex">
21
21
  <%= @action.message %>
22
22
  </div>
23
- <%= form.hidden_field :resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
23
+ <%= form.hidden_field :avo_resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
24
+ <%= form.hidden_field :avo_selected_query, 'data-action-target': 'selectedAllQuery' %>
24
25
  <% if @action.get_fields.present? %>
25
26
  <div class="mt-4">
26
27
  <% @action.get_fields.each_with_index do |field, index| %>
@@ -12,6 +12,7 @@
12
12
  parent_model: @parent_model,
13
13
  parent_resource: @parent_resource,
14
14
  applied_filters: @applied_filters,
15
+ query: @query,
15
16
  )
16
17
  %>
17
18
  <% end %>
@@ -44,7 +44,7 @@
44
44
  ""
45
45
  end
46
46
  %>
47
- <th class="text-left uppercase px-3 py-2 whitespace-nowrap rounded-l" data-control="resource-field-th">
47
+ <th class="text-left uppercase px-3 py-3 whitespace-nowrap rounded-l" data-control="resource-field-th">
48
48
  <% if field.sortable %>
49
49
  <%= link_to params.permit!.merge(sort_by: sort_by, sort_direction: sort_direction), class: "flex items-center #{classes} #{'cursor-pointer' if field.sortable}", 'data-turbo-frame': params[:turbo_frame] do %>
50
50
  <%= field.name %>
@@ -20,10 +20,10 @@
20
20
 
21
21
  <%= a_link url_for(params.permit!.merge(view_type: type)).to_s,
22
22
  icon: info[type][:new_icon],
23
- color: is_active_view ? :gray : :primary,
23
+ color: is_active_view ? :primary : :gray,
24
24
  rounded: false,
25
25
  size: :sm,
26
- class: is_active_view ? ' bg-gray-100 border-gray-300' : ' z-20',
26
+ class: is_active_view ? "z-20" : "bg-gray-100 border-gray-300",
27
27
  title: t('avo.switch_to_view', view_type: type),
28
28
  data: {
29
29
  tippy: 'tooltip',
@@ -26,10 +26,10 @@ module Avo
26
26
  items_holder.panel name, **args, &block
27
27
  end
28
28
 
29
- def tabs(&block)
29
+ def tabs(**args, &block)
30
30
  ensure_items_holder_initialized
31
31
 
32
- items_holder.tabs Avo::TabGroupBuilder.parse_block(&block)
32
+ items_holder.tabs Avo::TabGroupBuilder.parse_block(**args, &block)
33
33
  end
34
34
 
35
35
  def tool(klass, **args)
@@ -34,6 +34,7 @@ module Avo
34
34
  attr_accessor :buttons_on_form_footers
35
35
  attr_accessor :main_menu
36
36
  attr_accessor :profile_menu
37
+ attr_accessor :tabs_style
37
38
 
38
39
  def initialize
39
40
  @root_path = "/avo"
@@ -78,6 +79,7 @@ module Avo
78
79
  @buttons_on_form_footers = false
79
80
  @main_menu = nil
80
81
  @profile_menu = nil
82
+ @tabs_style = :tabs
81
83
  end
82
84
 
83
85
  def current_user_method(&block)
@@ -61,7 +61,7 @@ module Avo
61
61
  @name = args[:name]
62
62
  @translation_key = args[:translation_key]
63
63
  @block = block
64
- @required = args[:required] || false
64
+ @required = args.dig(:required) # Value if :required present on args, nil otherwise
65
65
  @readonly = args[:readonly] || false
66
66
  @sortable = args[:sortable] || false
67
67
  @nullable = args[:nullable] || false
@@ -8,9 +8,23 @@ module Avo
8
8
  if required.respond_to? :call
9
9
  Avo::Hosts::ViewRecordHost.new(block: required, record: model, view: view).handle
10
10
  else
11
- required
11
+ required.nil? ? required_from_validators : required
12
12
  end
13
13
  end
14
+
15
+ private
16
+
17
+ def required_from_validators
18
+ return false if model.nil?
19
+
20
+ validators.any? do |validator|
21
+ validator.kind_of? ActiveModel::Validations::PresenceValidator
22
+ end
23
+ end
24
+
25
+ def validators
26
+ model.class.validators_on(id)
27
+ end
14
28
  end
15
29
  end
16
30
  end
@@ -0,0 +1,47 @@
1
+ module Avo
2
+ module Services
3
+ class EncryptionService
4
+ attr_reader :message
5
+ attr_reader :purpose
6
+ attr_reader :crypt
7
+
8
+ class << self
9
+ def encrypt(message:, purpose:)
10
+ new(message: message, purpose: purpose).encrypt
11
+ end
12
+
13
+ def decrypt(message:, purpose:)
14
+ new(message: message, purpose: purpose).decrypt
15
+ end
16
+ end
17
+
18
+ def initialize(message:, purpose:)
19
+ @message = message
20
+ @purpose = purpose
21
+ @crypt = ActiveSupport::MessageEncryptor.new(encryption_key)
22
+ end
23
+
24
+ def encrypt
25
+ crypt.encrypt_and_sign(message, purpose: purpose)
26
+ end
27
+
28
+ def decrypt
29
+ crypt.decrypt_and_verify(message, purpose: purpose)
30
+ end
31
+
32
+ private
33
+
34
+ def encryption_key
35
+ secret_key_base[0..31]
36
+ rescue
37
+ # This will fail the decryption process.
38
+ # It's here only to keep Avo from crashing
39
+ SecureRandom.random_bytes(32)
40
+ end
41
+
42
+ def secret_key_base
43
+ Rails.application.secrets.secret_key_base || ENV['SECRET_KEY_BASE']
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/avo/tab_group.rb CHANGED
@@ -7,11 +7,13 @@ class Avo::TabGroup
7
7
  attr_reader :view
8
8
  attr_accessor :index
9
9
  attr_accessor :items_holder
10
+ attr_accessor :style
10
11
 
11
- def initialize(index: 0, view: nil)
12
+ def initialize(index: 0, view: nil, style: nil)
12
13
  @index = index
13
14
  @items_holder = Avo::ItemsHolder.new
14
15
  @view = view
16
+ @style = style
15
17
  end
16
18
 
17
19
  def hydrate(view: nil)
@@ -1,7 +1,7 @@
1
1
  class Avo::TabGroupBuilder
2
2
  class << self
3
- def parse_block(&block)
4
- Docile.dsl_eval(new, &block).build
3
+ def parse_block(**args, &block)
4
+ Docile.dsl_eval(new(**args), &block).build
5
5
  end
6
6
  end
7
7
 
@@ -9,8 +9,8 @@ class Avo::TabGroupBuilder
9
9
 
10
10
  delegate :tab, to: :items_holder
11
11
 
12
- def initialize
13
- @group = Avo::TabGroup.new
12
+ def initialize(style: nil)
13
+ @group = Avo::TabGroup.new(style: style)
14
14
  @items_holder = Avo::ItemsHolder.new
15
15
  end
16
16
 
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.13.6.pre.2" unless const_defined?(:VERSION)
2
+ VERSION = "2.14.1" unless const_defined?(:VERSION)
3
3
  end
@@ -52,6 +52,7 @@ Avo.configure do |config|
52
52
  # config.display_license_request_timeout_error = true
53
53
  # config.disabled_features = []
54
54
  # config.resource_controls = :right
55
+ # config.tabs_style = :tabs # can be :tabs or :pills
55
56
 
56
57
 
57
58
  ## == Breadcrumbs ==
@@ -23,7 +23,9 @@ en:
23
23
  you_missed_something_check_form: 'You might have missed something. Please check the form.'
24
24
  remove_selection: 'Remove selection'
25
25
  select_item: 'Select item'
26
- select_all: 'Select all on page'
26
+ select_all: 'Select all'
27
+ select_all_matching: 'Select all matching'
28
+ undo: undo
27
29
  delete_file: 'Delete file'
28
30
  delete: 'delete'
29
31
  delete_item: 'Delete %{item}'
@@ -113,3 +115,5 @@ en:
113
115
  empty_dashboard_message: Add cards to this dashboard
114
116
  no_cards_present: No cards present
115
117
  no_options_available: No options available
118
+ x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> records selected on this page from a total of <span class="font-bold text-gray-700">%{count}</span>
119
+ x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> records selected from all pages
@@ -24,6 +24,8 @@ fr:
24
24
  remove_selection: 'Supprimer la sélection'
25
25
  select_item: 'Sélectionnez un élément'
26
26
  select_all: 'Sélectionner tout sur la page'
27
+ select_all_matching: 'Sélectionner toutes les correspondances'
28
+ undo: annuler
27
29
  delete_file: 'Supprimer le fichier'
28
30
  delete: 'supprimer'
29
31
  delete_item: 'Supprimer %{item}'
@@ -113,3 +115,5 @@ fr:
113
115
  empty_dashboard_message: Ajouter des cartes à ce tableau de bord
114
116
  no_cards_present: Aucune carte présente
115
117
  no_options_available: Aucune option disponible
118
+ x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> enregistrements sélectionnés sur cette page sur un total de <span class="font-bold text-gray-700">%{count}</span>
119
+ x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> enregistrements sélectionnés dans toutes les pages
@@ -23,6 +23,9 @@ nb-NO:
23
23
  you_missed_something_check_form: 'Her mangler du noe. Vennligst sjekk skjemaet.'
24
24
  remove_selection: 'Fjern valg'
25
25
  select_item: 'Velg'
26
+ select_all: 'Velg alle'
27
+ select_all_matching: 'Velg alle samsvarende'
28
+ undo: angre
26
29
  delete_file: 'Slett fil'
27
30
  delete: 'slett'
28
31
  delete_item: 'Slett %{item}'
@@ -85,4 +88,6 @@ nb-NO:
85
88
  empty_dashboard_message: Legg til kort i dette dashbordet
86
89
  no_cards_present: Ingen kort til stede
87
90
  no_options_available: Ingen tilgjengelige alternativer
91
+ x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> poster valgt på denne siden fra totalt <span class="font-bold text-gray-700">%{count}</span>
92
+ x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> poster valgt fra alle sider
88
93
 
@@ -23,6 +23,9 @@ pt-BR:
23
23
  you_missed_something_check_form: 'Você pode ter esquecido algo. Por favor, cheque o formulário.'
24
24
  remove_selection: 'Remover seleção'
25
25
  select_item: 'Selecionar item'
26
+ select_all: 'Selecionar tudo'
27
+ select_all_matching: 'Selecione todas as correspondências'
28
+ undo: desfazer
26
29
  delete_file: 'Deletar arquivo'
27
30
  delete: 'deletar'
28
31
  delete_item: 'Deletar %{item}'
@@ -87,3 +90,5 @@ pt-BR:
87
90
  empty_dashboard_message: Adicionar cartões a este painel
88
91
  no_cards_present: Nenhum cartão presente
89
92
  no_options_available: Nenhuma opção disponível
93
+ x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> registros selecionados nesta página de um total de <span class="font-bold text-gray-700">%{count}</span>
94
+ x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> registros selecionados de todas as páginas
@@ -16,6 +16,10 @@ ro:
16
16
  resource_created: 'Resursa creata'
17
17
  resource_destroyed: 'Resursa stearsa'
18
18
  remove_selection: 'Sterge selectia'
19
+ select_item: 'Selecteaza record'
20
+ select_all: 'Selecteaza totul'
21
+ select_all_matching: 'Selecteaza toate care se potrivesc'
22
+ undo: Anuleaza
19
23
  delete_file: 'Sterge fisierul'
20
24
  delete: 'sterge'
21
25
  delete_item: 'Sterge %{item}'
@@ -83,3 +87,5 @@ ro:
83
87
  empty_dashboard_message: Adauga carduri in acest dashboard
84
88
  no_cards_present: Niciun card disponibil
85
89
  no_options_available: Nicio optiune disponibila
90
+ x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> selectate dintr-un total de <span class="font-bold text-gray-700">%{count}</span>
91
+ x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> selectate din toate paginile
@@ -6315,6 +6315,10 @@ trix-editor .attachment__metadata .attachment__size {
6315
6315
  top:-1px
6316
6316
  }
6317
6317
 
6318
+ .-top-\[0\.1rem\]{
6319
+ top:-0.1rem
6320
+ }
6321
+
6318
6322
  .right-3{
6319
6323
  right:0.75rem
6320
6324
  }
@@ -6527,6 +6531,26 @@ trix-editor .attachment__metadata .attachment__size {
6527
6531
  margin-left:50%
6528
6532
  }
6529
6533
 
6534
+ .ml-10{
6535
+ margin-left:2.5rem
6536
+ }
6537
+
6538
+ .mt-0\.5{
6539
+ margin-top:0.125rem
6540
+ }
6541
+
6542
+ .mt-0{
6543
+ margin-top:0px
6544
+ }
6545
+
6546
+ .mt-1\.5{
6547
+ margin-top:0.375rem
6548
+ }
6549
+
6550
+ .ml-2{
6551
+ margin-left:0.5rem
6552
+ }
6553
+
6530
6554
  .mr-0\.5{
6531
6555
  margin-right:0.125rem
6532
6556
  }
@@ -6547,10 +6571,6 @@ trix-editor .attachment__metadata .attachment__size {
6547
6571
  margin-bottom:-0.5rem
6548
6572
  }
6549
6573
 
6550
- .mt-0{
6551
- margin-top:0px
6552
- }
6553
-
6554
6574
  .mt-6{
6555
6575
  margin-top:1.5rem
6556
6576
  }
@@ -6687,6 +6707,10 @@ trix-editor .attachment__metadata .attachment__size {
6687
6707
  height:2.5rem
6688
6708
  }
6689
6709
 
6710
+ .h-9{
6711
+ height:2.25rem
6712
+ }
6713
+
6690
6714
  .max-h-\[42rem\]{
6691
6715
  max-height:42rem
6692
6716
  }
@@ -6795,6 +6819,14 @@ trix-editor .attachment__metadata .attachment__size {
6795
6819
  min-width:20px
6796
6820
  }
6797
6821
 
6822
+ .min-w-\[2rem\]{
6823
+ min-width:2rem
6824
+ }
6825
+
6826
+ .min-w-\[6rem\]{
6827
+ min-width:6rem
6828
+ }
6829
+
6798
6830
  .max-w-168{
6799
6831
  max-width:42rem
6800
6832
  }
@@ -7723,6 +7755,10 @@ trix-editor .attachment__metadata .attachment__size {
7723
7755
  padding-bottom:75%
7724
7756
  }
7725
7757
 
7758
+ .pt-px{
7759
+ padding-top:1px
7760
+ }
7761
+
7726
7762
  .pr-2{
7727
7763
  padding-right:0.5rem
7728
7764
  }
@@ -9181,6 +9217,10 @@ trix-editor {
9181
9217
  outline-width:1px
9182
9218
  }
9183
9219
 
9220
+ .active\:outline-0:active{
9221
+ outline-width:0px
9222
+ }
9223
+
9184
9224
  .active\:outline-slate-500:active{
9185
9225
  outline-color:#64748b
9186
9226
  }