pg_rails 7.6.21.pre.3 → 7.6.21.pre.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +14 -1
  3. data/pg_associable/spec/system/associable_spec.rb +1 -2
  4. data/pg_engine/app/components/inline_edit/inline_show_component.html.slim +2 -0
  5. data/pg_engine/app/controllers/pg_engine/base_controller.rb +1 -1
  6. data/pg_engine/app/controllers/users/accounts_controller.rb +20 -1
  7. data/pg_engine/app/controllers/users/invitations_controller.rb +2 -0
  8. data/pg_engine/app/decorators/account_decorator.rb +8 -8
  9. data/pg_engine/app/decorators/user_account_decorator.rb +7 -4
  10. data/pg_engine/app/helpers/pg_engine/flash_helper.rb +2 -1
  11. data/pg_engine/app/mailers/pg_engine/base_devise_mailer.rb +9 -0
  12. data/pg_engine/app/mailers/pg_engine/user_mailer.rb +2 -0
  13. data/pg_engine/app/models/account.rb +2 -1
  14. data/pg_engine/app/models/current.rb +1 -0
  15. data/pg_engine/app/models/user.rb +8 -0
  16. data/pg_engine/app/policies/pg_engine/base_policy.rb +12 -9
  17. data/pg_engine/app/views/users/accounts/_form.html.slim +1 -1
  18. data/pg_engine/app/views/users/accounts/show.html.slim +5 -4
  19. data/pg_engine/config/initializers/devise.rb +1 -1
  20. data/pg_engine/config/locales/es.yml +3 -2
  21. data/pg_engine/lib/pg_engine/engine.rb +9 -0
  22. data/pg_engine/spec/mailers/previews/devise_preview.rb +6 -0
  23. data/pg_layout/app/javascript/controllers/notifications_controller.js +3 -1
  24. data/pg_layout/app/views/devise/mailer/invitation_instructions.html.erb +3 -5
  25. data/pg_layout/app/views/devise/mailer/invitation_instructions.text.erb +3 -5
  26. data/pg_layout/app/views/layouts/pg_layout/base.html.slim +2 -3
  27. data/pg_layout/app/views/layouts/pg_layout/containerized.html.slim +1 -1
  28. data/pg_layout/app/views/layouts/pg_layout/devise_mailer.html.slim +12 -0
  29. data/pg_layout/app/views/layouts/pg_layout/devise_mailer.text.erb +7 -0
  30. data/pg_layout/app/views/pg_layout/_navbar.html.slim +50 -0
  31. data/pg_layout/app/views/pg_layout/_sidebar.html.slim +10 -0
  32. data/pg_layout/app/views/pg_layout/_sidebar_mobile.html.slim +17 -0
  33. data/pg_layout/app/views/pg_layout/_signed_in_links.html.slim +53 -51
  34. data/pg_rails/lib/version.rb +1 -1
  35. metadata +8 -5
  36. data/pg_layout/app/views/pg_layout/_navbar.html.erb +0 -52
  37. data/pg_layout/app/views/pg_layout/_sidebar.html.erb +0 -24
  38. data/pg_layout/app/views/pg_layout/_sidebar_mobile.html.erb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c7e8b1261e1be1d5db2d19ca5b4102f0bca77ae9f379da78249d2087e44736b
4
- data.tar.gz: 455549bec4416393199d4b713cb653f008e4ff42a4d70f4923a1aff7b9dc1e78
3
+ metadata.gz: 2f515ba243d4ef8862ebb74652329637397334f2af37b82a3984a6cab05bf2ab
4
+ data.tar.gz: 7f01717d0f4a9e4ff9aeca5a24286134cf4045c3554986e716c5aa33c6d5a9fd
5
5
  SHA512:
6
- metadata.gz: a94f33c4e747a6bae8d710c9a25ffea315f8d49cfadee1d111396381203d90c7716e160e45b6e5348b7389d4b0ef409c45c8d67b9df0fd8215ac111e84919b1a
7
- data.tar.gz: f399f20faaccb9a7f9d5aa49c349faa67e1b1e7e56f850ba023f3a1b1471c1d35607dac07ee4fd1d8b39f733979add05bb0e98238b6352378cfe9fdb179a040c
6
+ metadata.gz: dd6e02da0ef6c884fa7bacf08c3cc38ee9677ba26c26e47d97eb313accdaf14ac82781a70ad54149f40c63b37b0313adf410f14e0b169866078f2d2f3fa30d09
7
+ data.tar.gz: 510037412f74089b74bd7cd632cf70fb2e25d57c0e7d4463d0667f723a4add732319f89f0f7670ccaa6c10874372ee87943c2f92d96fa789badbd04ed4d4fde0
@@ -49,6 +49,13 @@ module PgAssociable
49
49
  puede_crear = Pundit::PolicyFinder.new(klass).policy.new(user, klass).new_from_associable?
50
50
  collection = Pundit::PolicyFinder.new(klass).scope.new(user, klass).resolve
51
51
  collection = collection.kept if collection.respond_to?(:kept)
52
+
53
+ reflect = associacion_for(atributo)
54
+ fkid = object.send(reflect.foreign_key)
55
+ if fkid
56
+ collection = collection.or(klass.where(id: fkid))
57
+ end
58
+
52
59
  [collection, puede_crear]
53
60
  end
54
61
 
@@ -78,11 +85,17 @@ module PgAssociable
78
85
  association atributo, options
79
86
  end
80
87
 
81
- def clase_asociacion(atributo)
88
+ def associacion_for(atributo)
82
89
  asociacion = object.class.reflect_on_all_associations.find { |a| a.name == atributo.to_sym }
83
90
 
84
91
  raise PgEngine::Error, "no existe la asociación para el atributo: #{atributo}" if asociacion.blank?
85
92
 
93
+ asociacion
94
+ end
95
+
96
+ def clase_asociacion(atributo)
97
+ asociacion = associacion_for(atributo)
98
+
86
99
  nombre_clase = asociacion.options[:class_name]
87
100
  nombre_clase = asociacion.name.to_s.camelize if nombre_clase.nil?
88
101
  Object.const_get(nombre_clase)
@@ -10,13 +10,12 @@ describe 'Associable' do
10
10
  visit path
11
11
  end
12
12
 
13
- fit do
13
+ it do
14
14
  fill_in 'cosa_nombre', with: 'La cosa'
15
15
  select 'Los', from: 'cosa_tipo'
16
16
  find('.cosa_categoria_de_cosa input[type=text]').click
17
17
  expect(page).to have_text :all, 'Nueva categoría de cosa'
18
18
  find('.cosa_categoria_de_cosa .list-group-item').click
19
- # select Account.first.to_s
20
19
  fill_in 'categoria_de_cosa_nombre', with: 'la categoría'
21
20
  select 'Completar', from: 'categoria_de_cosa_tipo'
22
21
  click_on 'Agregar Categoría de cosa'
@@ -1,3 +1,5 @@
1
+ / TODO!: estaría bueno que la policy pueda discriminar permisos para cada atributo
2
+ / y por ejemplo no permitir el edit de un belongs_to a un modelo sobre el cual no tiene permisos
1
3
  - if Current.namespace == :tenant && \
2
4
  @model.class.inline_editable?(@unsuffixed_attribute) && helpers.policy(@model).edit?
3
5
  = helpers.turbo_frame_tag(@frame_id, class: 'inline-edit')
@@ -219,7 +219,7 @@ module PgEngine
219
219
  Request: #{request.inspect}
220
220
  STRING
221
221
 
222
- render_my_component(BadUserInputComponent.new(error_msg: 'Acceso no autorizado'), :unauthorized)
222
+ render_my_component(BadUserInputComponent.new(error_msg: 'Operación no permitida'), :unauthorized)
223
223
  end
224
224
 
225
225
  def go_back(message = nil, type: :alert)
@@ -17,6 +17,25 @@ module Users
17
17
 
18
18
  add_breadcrumb Account.model_name.human(count: 2), ->(h) { h.users_accounts_path(tid: nil) }
19
19
 
20
+ layout :set_layout
21
+ def set_layout
22
+ if action_name == 'index'
23
+ 'pg_layout/containerized'
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ before_action do
30
+ if action_name.in? %w[index]
31
+ @container_class = 'container border p-0 my-3'
32
+ @container_style = 'max-width: 50em; xborder-left: 1px solid grey'
33
+ elsif action_name.in? %w[edit update]
34
+ @container_class = 'container border pb-3 my-3'
35
+ @container_style = 'max-width: 50em; xborder-left: 1px solid grey'
36
+ end
37
+ end
38
+
20
39
  # La user_account puede estar disabled
21
40
  def show
22
41
  add_breadcrumb @account, users_account_path(@account, tid: nil)
@@ -56,7 +75,7 @@ module Users
56
75
  end
57
76
 
58
77
  def atributos_para_listar
59
- %i[nombre plan owner]
78
+ %i[nombre owner]
60
79
  end
61
80
  end
62
81
  end
@@ -10,6 +10,8 @@ module Users
10
10
  add_breadcrumb 'Agregar usuario'
11
11
  @sidebar = false
12
12
  @no_main_frame = true
13
+ @container_class = 'container border pb-3 my-3'
14
+ @container_style = 'max-width: 50em; xborder-left: 1px solid grey'
13
15
  end
14
16
 
15
17
  def new
@@ -22,13 +22,13 @@ class AccountDecorator < PgEngine::BaseRecordDecorator
22
22
  ua.reject_invitation_link].compact.join.html_safe
23
23
  end
24
24
 
25
- # def show_link(text: '', klass: 'btn-light')
26
- # return unless Pundit.policy!(Current.user, object).show?
25
+ def show_link(text: 'Usuarios', klass: 'btn-secondary')
26
+ return unless Pundit.policy!(Current.user, object).show?
27
27
 
28
- # helpers.content_tag :span, 'data-controller': :tooltip, title: 'Más opciones' do
29
- # helpers.link_to object_url, class: "btn btn-sm #{klass}" do
30
- # helpers.content_tag(:span, nil, class: clase_icono('list')) + text
31
- # end
32
- # end
33
- # end
28
+ helpers.content_tag :span do
29
+ helpers.link_to object_url, class: "btn btn-sm #{klass}" do
30
+ helpers.content_tag(:span, nil, class: clase_icono('person')) + text
31
+ end
32
+ end
33
+ end
34
34
  end
@@ -8,10 +8,13 @@ class UserAccountDecorator < PgEngine::BaseRecordDecorator
8
8
  def ingresar_link
9
9
  return unless Pundit.policy!(Current.user, object).ingresar?
10
10
 
11
- h.link_to h.tenant_root_path(tid: object.to_param),
12
- 'data-turbo-frame': :_top,
13
- class: 'btn btn-sm btn-primary' do
14
- '<i class="bi bi-box-arrow-in-right"></i> Ingresar'.html_safe
11
+ # El span es necesario para que el tamaño de los botones sea homogéneo
12
+ helpers.content_tag :span do
13
+ h.link_to h.tenant_root_path(tid: object.to_param),
14
+ 'data-turbo-frame': :_top,
15
+ class: 'btn btn-sm btn-primary' do
16
+ '<i class="bi bi-box-arrow-in-right"></i> Ingresar'.html_safe
17
+ end
15
18
  end
16
19
  end
17
20
 
@@ -9,7 +9,8 @@ module PgEngine
9
9
  end
10
10
 
11
11
  def render_turbo_stream_title
12
- title = [breadcrumbs.last&.name, ActsAsTenant.current_tenant, I18n.t('app_name')].compact.join(' - ')
12
+ title = [breadcrumbs.last&.name, ActsAsTenant.current_tenant,
13
+ I18n.t(Current.app_name, scope: 'app_name')].compact.join(' - ')
13
14
  turbo_stream.update_all 'title', title
14
15
  end
15
16
  end
@@ -0,0 +1,9 @@
1
+ module PgEngine
2
+ class BaseDeviseMailer < ApplicationMailer
3
+ before_action do
4
+ @footer_image_src = 'mail-footer-lg.png'
5
+ end
6
+
7
+ layout 'pg_layout/devise_mailer'
8
+ end
9
+ end
@@ -9,6 +9,8 @@ module PgEngine
9
9
  mail(to: @recipient.email, subject: params[:subject])
10
10
  end
11
11
 
12
+ private
13
+
12
14
  def replace_user(input)
13
15
  # reemplaza todas las ocurrencias de: %{user}
14
16
  format(input, user: @recipient.nombre)
@@ -30,7 +30,7 @@ class Account < ApplicationRecord
30
30
  belongs_to :creado_por, optional: true, class_name: 'User'
31
31
  belongs_to :actualizado_por, optional: true, class_name: 'User'
32
32
 
33
- enumerize :plan, in: { completar: 0, los: 1, valores: 2 }
33
+ enumerize :plan, in: { factura: 0, procura: 1 }
34
34
 
35
35
  validates :plan, :nombre, presence: true
36
36
 
@@ -61,6 +61,7 @@ class Account < ApplicationRecord
61
61
  end
62
62
 
63
63
  def to_s
64
+ # TODO: nombre_in_database?
64
65
  nombre
65
66
  end
66
67
 
@@ -1,5 +1,6 @@
1
1
  class Current < ActiveSupport::CurrentAttributes
2
2
  attribute :user, :namespace, :controller, :active_user_account
3
+ attribute :app_name, default: :procura
3
4
  # attribute :request_id, :user_agent, :ip_address
4
5
 
5
6
  # resets { Time.zone = nil }
@@ -89,6 +89,14 @@ class User < ApplicationRecord
89
89
  user_accounts.first.invitation_status = :ist_invited
90
90
  end
91
91
 
92
+ def invited_to_app
93
+ user_accounts.first.account.plan || 'procura'
94
+ rescue StandardError => e
95
+ pg_err(e)
96
+
97
+ 'procura'
98
+ end
99
+
92
100
  attr_accessor :orphan
93
101
 
94
102
  def active_for_authentication?
@@ -82,15 +82,15 @@ module PgEngine
82
82
  end
83
83
 
84
84
  def puede_editar?
85
- user_has_profile(:update)
85
+ user_has_profile?(:update)
86
86
  end
87
87
 
88
88
  def puede_crear?
89
- user_has_profile(:create)
89
+ user_has_profile?(:create)
90
90
  end
91
91
 
92
92
  def puede_borrar?
93
- user_has_profile(:destroy)
93
+ user_has_profile?(:destroy)
94
94
  end
95
95
 
96
96
  def puede_ver_archivados?
@@ -98,19 +98,19 @@ module PgEngine
98
98
  model = record.is_a?(ActiveRecord::Base) ? record.class : record
99
99
  model.respond_to?(:discarded)
100
100
  end
101
- user_has_profile(:archive) && admits_discard
101
+ user_has_profile?(:archive) && admits_discard
102
102
  end
103
103
 
104
104
  def base_access_to_record?
105
- user_has_profile(:read)
105
+ user_has_profile?(:read)
106
106
  end
107
107
 
108
108
  def base_access_to_collection?
109
- user_has_profile(:read)
109
+ user_has_profile?(:read)
110
110
  end
111
111
 
112
112
  def export?
113
- user_has_profile(:export)
113
+ user_has_profile?(:export)
114
114
  end
115
115
 
116
116
  def record_discarded?
@@ -125,12 +125,15 @@ module PgEngine
125
125
  record.model_name.plural
126
126
  end
127
127
 
128
- def user_has_profile(key)
128
+ def user_has_profile?(key)
129
129
  return true if Current.namespace == :admin
130
130
  return false if ActsAsTenant.current_tenant.blank?
131
131
 
132
132
  full_key = "#{profile_prefix}__#{key}"
133
- Current.user_account_owner? || Current.active_user_profiles.include?(full_key)
133
+
134
+ scoped_by_tenant = record.class.respond_to?(:scoped_by_tenant) && record.class.scoped_by_tenant?
135
+ (!scoped_by_tenant || Current.account.id == record.account_id) &&
136
+ (Current.user_account_owner? || Current.active_user_profiles.include?(full_key))
134
137
  end
135
138
  end
136
139
  end
@@ -1,7 +1,7 @@
1
1
  div style="max-width: 22em"
2
2
  = pg_form_for(@account || object) do |f|
3
3
  = f.input :nombre
4
- = f.input :plan
4
+ / = f.input :plan
5
5
  = f.input :logo
6
6
  .mt-2
7
7
  = f.button :submit
@@ -3,10 +3,11 @@
3
3
  = @user_account.sign_off_link
4
4
 
5
5
  .text-center
6
- - if @account.logo.present?
7
- = image_tag @account.logo
8
- h1
9
- = @account
6
+ .d-flex.justify-content-center.gap-2.align-items-center.m-3
7
+ - if @account.logo.present?
8
+ = image_tag @account.logo, style: 'max-height:3em'
9
+ .fs-1
10
+ = @account
10
11
 
11
12
  / h6
12
13
  |> Administrado por:
@@ -30,7 +30,7 @@ Devise.setup do |config|
30
30
  # config.mailer = 'Devise::Mailer'
31
31
 
32
32
  # Configure the parent class responsible to send e-mails.
33
- config.parent_mailer = 'ApplicationMailer'
33
+ config.parent_mailer = 'PgEngine::BaseDeviseMailer'
34
34
 
35
35
  # ==> ORM configuration
36
36
  # Load and configure the ORM. Supports :active_record (default) and
@@ -141,10 +141,11 @@ es:
141
141
  invitation_instructions:
142
142
  subject: "Recibiste una invitación de %{inviter}"
143
143
  hello: "Hola %{email}"
144
- someone_invited_you: "Has sido invitado a %{url}, puedes aceptarlo siguiendo el siguiente enlace"
144
+ someone_invited_you: "Hola! %{inviter} te invitó a su espacio en %{app_name}"
145
+ follow_link: "Podés aceptar la invitación en el siguiente link:"
145
146
  accept: "Aceptar la invitación"
146
147
  accept_until: "Esta invitación expirará en %{due_date}."
147
- ignore: "Si no le interesa esta invitación, simplemente ignore este correo. No se creará tu cuenta hasta que accedas al enlace anterior y crees una contraseña."
148
+ ignore: "Si no te interesa esta invitación, simplemente ignora este correo. No se creará tu cuenta hasta que accedas al enlace anterior."
148
149
  confirmation_instructions:
149
150
  action: Confirmá tu cuenta
150
151
  greeting: "Hola %{recipient}"
@@ -20,6 +20,15 @@ module PgEngine
20
20
  load override
21
21
  end
22
22
 
23
+ # TODO!: mover a otro lugar?
24
+ Devise.mailer.class_eval do
25
+ def invitation_instructions(record, token, opts = {})
26
+ @token = token
27
+ opts.merge!(subject: I18n.t('devise.mailer.invitation_instructions.subject', inviter: record.invited_by))
28
+ devise_mail(record, :invitation_instructions, opts)
29
+ end
30
+ end
31
+
23
32
  ActiveStorage::BaseController.class_eval do
24
33
  around_action :set_without_tenant
25
34
 
@@ -10,4 +10,10 @@ class DevisePreview < ActionMailer::Preview
10
10
  # ClienteMailer.comprobante_recibido(VComprobante.find(params[:]))
11
11
  Devise::Mailer.reset_password_instructions(User.first, 'TOKENN')
12
12
  end
13
+
14
+ def invitation
15
+ # ClienteMailer.comprobante_recibido(VComprobante.find(params[:]))
16
+ invitee = User.invitation_not_accepted.first
17
+ Devise::Mailer.invitation_instructions(invitee, 'TOKENN')
18
+ end
13
19
  end
@@ -49,7 +49,9 @@ export default class extends Controller {
49
49
  notif.classList.remove('unseen')
50
50
  }
51
51
  )
52
- document.querySelector('.notifications-unseen-mark').remove()
52
+ document.querySelectorAll('.notifications-unseen-mark').forEach((e) => {
53
+ e.remove()
54
+ })
53
55
  } else {
54
56
  const text = await response.text
55
57
  Rollbar.error('Error marking as seen: ', text)
@@ -1,11 +1,9 @@
1
- <p><%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %></p>
1
+ <p><%= t("devise.mailer.invitation_instructions.someone_invited_you", inviter: @resource.invited_by, app_name: I18n.t(@resource.invited_to_app, scope: 'app_name')) %></p>
2
2
 
3
- <p><%= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url) %></p>
3
+ <p><%= t("devise.mailer.invitation_instructions.follow_link") %></p>
4
4
 
5
5
  <p><%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, invitation_token: @token) %></p>
6
6
 
7
- <% if @resource.invitation_due_at %>
7
+ <% if false # @resource.invitation_due_at %>
8
8
  <p><%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %></p>
9
9
  <% end %>
10
-
11
- <p><%= t("devise.mailer.invitation_instructions.ignore") %></p>
@@ -1,11 +1,9 @@
1
- <%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %>
1
+ <%= t("devise.mailer.invitation_instructions.someone_invited_you", inviter: @resource.invited_by, app_name: I18n.t(@resource.invited_to_app, scope: 'app_name')) %>
2
2
 
3
- <%= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url) %>
3
+ <%= t("devise.mailer.invitation_instructions.follow_link") %>
4
4
 
5
5
  <%= accept_invitation_url(@resource, invitation_token: @token) %>
6
6
 
7
- <% if @resource.invitation_due_at %>
7
+ <% if false # @resource.invitation_due_at %>
8
8
  <%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %>
9
9
  <% end %>
10
-
11
- <%= t("devise.mailer.invitation_instructions.ignore") %>
@@ -9,7 +9,7 @@ html
9
9
  meta name="turbo-visit-control" content="reload"
10
10
 
11
11
  - cache :title_icon
12
- title = t('app_name')
12
+ title = t(Current.app_name, scope: 'app_name')
13
13
  - begin
14
14
  = render partial: 'layouts/favicon'
15
15
  - rescue ActionView::MissingTemplate => e
@@ -53,8 +53,7 @@ html
53
53
  body
54
54
  span#tid.d-none data-tid="#{Current.tid}"
55
55
  - sidebar_present = @navbar.present? && @sidebar != false
56
- - if sidebar_present
57
- = render partial: 'pg_layout/sidebar_mobile'
56
+ = render partial: 'pg_layout/sidebar_mobile'
58
57
 
59
58
  div class="#{ 'with-sidebar' if sidebar_present }"
60
59
  - if sidebar_present
@@ -1,5 +1,5 @@
1
1
  - content_for :content do
2
- div class="pt-3 #{modal_targeted? ? '' : 'container-fluid'}"
2
+ div class="pt-3 #{modal_targeted? ? '' : @container_class || 'container-fluid'}" style=@container_style
3
3
  = content_for?(:containerized_content) ? yield(:containerized_content) : yield
4
4
 
5
5
  = render template: 'layouts/pg_layout/base'
@@ -0,0 +1,12 @@
1
+ html
2
+ body style="font-family: sans-serif"
3
+ center
4
+ = yield
5
+
6
+ - if @footer_href.present?
7
+ footer style="margin-top: 2em;"
8
+ = link_to @footer_href, rel: 'noreferrer', target: :_blank do
9
+ - if @footer_image_src.present?
10
+ = image_tag @footer_image_src, alt: @footer_image_alt
11
+ - else
12
+ = @footer_image_alt
@@ -0,0 +1,7 @@
1
+ <%= yield %>
2
+
3
+ <% if @footer_href.present? %>
4
+ ----------------------
5
+ <%= @footer_image_alt %>
6
+ <%= @footer_href %>
7
+ <% end %>
@@ -0,0 +1,50 @@
1
+ nav class="navbar navbar-expand-#{@breakpoint_navbar_expand}" data-bs-theme="dark"
2
+ .container-fluid.xgap-2
3
+ div
4
+ - unless @sidebar == false
5
+ button data-controller="navbar" data-action="navbar#expandNavbar" class="btn btn-outline-light me-2 d-none d-#{@breakpoint_navbar_expand}-inline-block"
6
+ i class="bi #{@navbar_chevron_class}"
7
+ - if @navbar.logo.present?
8
+ span.ms-3
9
+ = render @navbar.logo
10
+ - if user_signed_in? && @notifications_bell.present?
11
+ div class="d-#{@breakpoint_navbar_expand}-none"
12
+ = render @notifications_bell
13
+ div
14
+ - if user_signed_in?
15
+ .collapse.navbar-collapse.justify-content-end
16
+ = render partial: 'pg_layout/signed_in_links'
17
+ - @navbar.extensiones.each do |extension|
18
+ = extension
19
+ div class="d-#{@breakpoint_navbar_expand}-none"
20
+ - if user_signed_in?
21
+ a.d-flex.align-items-center.gap-2 href="#" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample"
22
+ - if Current.account.present?
23
+ - if Current.account.logo.present?
24
+ = image_tag Current.account.logo.variant(:thumb), class: 'rounded-circle border border-2 me-2', width: 40, height: 40
25
+ - else
26
+ i.bi.bi-bag-fill.me-2 style="font-size: 1.7em"
27
+ - if Current.user.avatar.present?
28
+ = image_tag Current.user.avatar.variant(:thumb), class: 'rounded-circle border border-2 me-2', width: 40, height: 40
29
+ - else
30
+ i.bi.bi-person-circle.me-2 style="font-size: 1.7em"
31
+ / - else
32
+ button class="btn btn-outline-light d-inline-block d-#{@breakpoint_navbar_expand}-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample"
33
+ i.bi.bi-list
34
+ #notifications-collapse.collapse[data-controller="notifications"]
35
+ #notifications
36
+ #notifications-inner
37
+ - if @notifications&.any?
38
+ = render NotificationComponent.with_collection(@notifications) if @notifications&.any?
39
+ - else
40
+ span.text-light.text-center
41
+ | No hay notificaciones
42
+ .text-center
43
+ button.btn.btn-link.text-light.btn-sm[type="button" data-bs-toggle="collapse" data-bs-target="#notifications-collapse"]
44
+ i.bi-chevron-up.fs-3
45
+ css:
46
+ @media(max-width: 767px) {
47
+ .navbar .navbar-brand {
48
+ visibility:visible!important;
49
+ }
50
+ }
@@ -0,0 +1,10 @@
1
+ div id="sidebar" class="#{@navbar_opened_class} flex-shrink-0 d-none d-#{@breakpoint_navbar_expand}-block"
2
+ .mt-1
3
+ .m-3
4
+ = render @navbar.logo if @navbar.logo.present?
5
+ ul.list-unstyled.ps-0.mt-5
6
+ - @navbar.sidebar.each do |entry|
7
+ - next if @navbar.hide_entry?(entry)
8
+ li.mb-1
9
+ a href=entry[:path] class="d-inline-flex text-decoration-none pg--nav-button #{@navbar.active_entry?(entry, request) ? 'active' : ''} #{entry[:attributes]}"
10
+ = entry[:title]
@@ -0,0 +1,17 @@
1
+ #offcanvasExample.offcanvas.offcanvas-end[tabindex="-1" aria-labelledby="offcanvasExampleLabel" data-bs-theme="dark"]
2
+ .offcanvas-header[data-bs-theme="dark"]
3
+ h5#offcanvasExampleLabel.offcanvas-title
4
+ button.btn-close[type="button" data-bs-dismiss="offcanvas" aria-label="Close"]
5
+ .offcanvas-body.text-end
6
+ - if user_signed_in?
7
+ = render partial: 'pg_layout/signed_in_links'
8
+ - if @navbar.present?
9
+ ul.list-unstyled.mt-4
10
+ - @navbar.sidebar.each do |entry|
11
+ - next if @navbar.hide_entry?(entry)
12
+ li
13
+ a href=entry[:path] class="pg--nav-button pe-4 text-light #{@navbar.active_entry?(entry, request) ? 'active' : ''} #{entry[:attributes]}"
14
+ = entry[:title]
15
+ css:
16
+ .offcanvas a { text-decoration: none; }
17
+ .offcanvas li { xmargin-top: 0.75em; }
@@ -1,52 +1,54 @@
1
- - if user_signed_in?
2
- .xcollapse.xnavbar-collapse.justify-content-end
3
- ul.navbar-nav.flex-row
4
- - if Current.account.present?
5
- li.nav-item.dropdown
6
- = link_to '#', class: 'nav-link dropdown-toggle py-0 d-flex align-items-center',
7
- role: :button, 'data-bs-toggle': :dropdown, 'aria-expanded': 'false' do
8
- - if Current.account.logo.present?
9
- = image_tag Current.account.logo.variant(:thumb), class: 'rounded-circle border border-2 me-2', width: 40, height: 40
10
- - else
11
- i.bi.bi-bag-fill.me-2 style="font-size: 1.7em"
12
- = Current.account
13
- ul.dropdown-menu
14
- - if @other_active_accounts&.any?
15
- h6.dropdown-header Cambiar a:
16
- - @other_active_accounts.each do |ua|
17
- li = link_to ua.account, tenant_root_path(tid: ua.to_param), class: 'dropdown-item'
18
- li
19
- hr.dropdown-divider
20
- li = link_to "Administrar #{Account.model_name.human(count: 2)}", users_accounts_path(tid: nil), class: 'dropdown-item'
21
- - elsif @other_active_accounts&.any?
22
- li.nav-item.dropdown.d-flex
23
- = link_to '#', class: 'nav-link dropdown-toggle py-0 d-flex align-items-center',
24
- role: :button, 'data-bs-toggle': :dropdown, 'aria-expanded': 'false' do
25
- i.bi.bi-bag-fill.me-2 style="font-size: 1.7em"
26
- = Account.model_name.human(count: 2)
27
- ul.dropdown-menu
28
- - @other_active_accounts.each do |ua|
29
- li = link_to ua.account, tenant_root_path(tid: ua.to_param), class: 'dropdown-item'
30
- li
31
- hr.dropdown-divider
32
- li = link_to "Administrar #{Account.model_name.human(count: 2).downcase}", users_accounts_path(tid: nil), class: 'dropdown-item'
1
+ ul.navbar-nav.gap-3.align-items-center class="gap-#{@breakpoint_navbar_expand}-0"
2
+ - if Current.account.present?
3
+ li.nav-item.dropdown
4
+ = link_to '#', class: 'nav-link dropdown-toggle py-0 d-flex align-items-center',
5
+ role: :button, 'data-bs-toggle': :dropdown, 'aria-expanded': 'false' do
6
+ - if Current.account.logo.present?
7
+ = image_tag Current.account.logo.variant(:thumb), class: 'rounded-circle border border-2 me-2', width: 40, height: 40
8
+ - else
9
+ i.bi.bi-bag-fill.me-2 style="font-size: 1.7em"
10
+ = Current.account
11
+ ul.dropdown-menu
12
+ li = link_to "Administrar #{Current.account}", users_account_path(Current.account, tid: nil), class: 'dropdown-item'
13
+ li
14
+ hr.dropdown-divider
15
+ - if @other_active_accounts&.any?
16
+ h6.dropdown-header Cambiar a:
17
+ - @other_active_accounts.each do |ua|
18
+ li = link_to ua.account, tenant_root_path(tid: ua.to_param), class: 'dropdown-item'
19
+ li
20
+ hr.dropdown-divider
21
+ li = link_to "Administrar #{Account.model_name.human(count: 2).downcase}", users_accounts_path(tid: nil), class: 'dropdown-item'
22
+ - elsif @other_active_accounts&.any?
23
+ li.nav-item.dropdown.d-flex
24
+ = link_to '#', class: 'nav-link dropdown-toggle py-0 d-flex align-items-center',
25
+ role: :button, 'data-bs-toggle': :dropdown, 'aria-expanded': 'false' do
26
+ i.bi.bi-bag-fill.me-2 style="font-size: 1.7em"
27
+ = Account.model_name.human(count: 2)
28
+ ul.dropdown-menu
29
+ - @other_active_accounts.each do |ua|
30
+ li = link_to ua.account, tenant_root_path(tid: ua.to_param), class: 'dropdown-item'
31
+ li
32
+ hr.dropdown-divider
33
+ li = link_to "Administrar #{Account.model_name.human(count: 2).downcase}", users_accounts_path(tid: nil), class: 'dropdown-item'
33
34
 
34
- .vr.bg-white.mx-3
35
- - if Current.user.present? && @notifications_bell.present?
36
- = render @notifications_bell
37
- .vr.bg-white.mx-3
38
- li.nav-item.dropdown.me-3
39
- = link_to '#', class: 'nav-link dropdown-toggle py-0 d-flex align-items-center',
40
- role: :button, 'data-bs-toggle': :dropdown, 'aria-expanded': 'false' do
41
- - if Current.user.avatar.present?
42
- = image_tag Current.user.avatar.variant(:thumb), class: 'rounded-circle border border-2 me-2', width: 40, height: 40
43
- - else
44
- i.bi.bi-person-circle.me-2 style="font-size: 1.7em"
45
- = Current.user
46
- ul.dropdown-menu
47
- li = link_to 'Mi cuenta', edit_user_registration_path(tid: nil), class: 'dropdown-item'
48
- li = link_to Account.model_name.human(count: 2), users_accounts_path(tid: nil), class: 'dropdown-item'
49
- - if Current.user.developer?
50
- li = link_to 'Admin', admin_users_path, class: 'dropdown-item'
51
- li = link_to 'Cerrar sesión', destroy_user_session_path(tid: nil),
52
- 'data-turbo-method': :delete, class: 'dropdown-item'
35
+ .vr.bg-white.mx-3.d-none class="d-#{@breakpoint_navbar_expand}-inline-block"
36
+ - if Current.user.present? && @notifications_bell.present?
37
+ .d-none class="d-#{@breakpoint_navbar_expand}-inline-block"
38
+ = render @notifications_bell
39
+ .vr.bg-white.mx-3.d-none class="d-#{@breakpoint_navbar_expand}-inline-block"
40
+ li.nav-item.dropdown.me-3
41
+ = link_to '#', class: 'nav-link dropdown-toggle py-0 d-flex align-items-center',
42
+ role: :button, 'data-bs-toggle': :dropdown, 'aria-expanded': 'false' do
43
+ - if Current.user.avatar.present?
44
+ = image_tag Current.user.avatar.variant(:thumb), class: 'rounded-circle border border-2 me-2', width: 40, height: 40
45
+ - else
46
+ i.bi.bi-person-circle.me-2 style="font-size: 1.7em"
47
+ = Current.user
48
+ ul.dropdown-menu
49
+ li = link_to 'Mi cuenta', edit_user_registration_path(tid: nil), class: 'dropdown-item'
50
+ li = link_to Account.model_name.human(count: 2), users_accounts_path(tid: nil), class: 'dropdown-item'
51
+ - if Current.user.developer?
52
+ li = link_to 'Admin', admin_users_path, class: 'dropdown-item'
53
+ li = link_to 'Cerrar sesión', destroy_user_session_path(tid: nil),
54
+ 'data-turbo-method': :delete, class: 'dropdown-item'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.6.21-3'
4
+ VERSION = '7.6.21-5'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.6.21.pre.3
4
+ version: 7.6.21.pre.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-03 00:00:00.000000000 Z
11
+ date: 2024-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -757,6 +757,7 @@ files:
757
757
  - pg_engine/app/lib/pg_engine/filtros_builder.rb
758
758
  - pg_engine/app/lib/pg_form_builder.rb
759
759
  - pg_engine/app/mailers/pg_engine/admin_mailer.rb
760
+ - pg_engine/app/mailers/pg_engine/base_devise_mailer.rb
760
761
  - pg_engine/app/mailers/pg_engine/base_mailer.rb
761
762
  - pg_engine/app/mailers/pg_engine/user_mailer.rb
762
763
  - pg_engine/app/models/account.rb
@@ -1017,13 +1018,15 @@ files:
1017
1018
  - pg_layout/app/views/layouts/pg_layout/container_logo.html.slim
1018
1019
  - pg_layout/app/views/layouts/pg_layout/containerized.html.slim
1019
1020
  - pg_layout/app/views/layouts/pg_layout/devise.html.slim
1021
+ - pg_layout/app/views/layouts/pg_layout/devise_mailer.html.slim
1022
+ - pg_layout/app/views/layouts/pg_layout/devise_mailer.text.erb
1020
1023
  - pg_layout/app/views/layouts/pg_layout/mailer.html.slim
1021
1024
  - pg_layout/app/views/layouts/pg_layout/mailer.text.erb
1022
1025
  - pg_layout/app/views/layouts/pg_layout/show.html.slim
1023
1026
  - pg_layout/app/views/pg_layout/_flash.html.slim
1024
- - pg_layout/app/views/pg_layout/_navbar.html.erb
1025
- - pg_layout/app/views/pg_layout/_sidebar.html.erb
1026
- - pg_layout/app/views/pg_layout/_sidebar_mobile.html.erb
1027
+ - pg_layout/app/views/pg_layout/_navbar.html.slim
1028
+ - pg_layout/app/views/pg_layout/_sidebar.html.slim
1029
+ - pg_layout/app/views/pg_layout/_sidebar_mobile.html.slim
1027
1030
  - pg_layout/app/views/pg_layout/_signed_in_links.html.slim
1028
1031
  - pg_layout/lib/pg_layout.rb
1029
1032
  - pg_layout/lib/pg_layout/engine.rb
@@ -1,52 +0,0 @@
1
- <nav class="navbar navbar-expand-<%= @breakpoint_navbar_expand %>" data-bs-theme="dark">
2
- <div class="container-fluid xgap-2">
3
- <% unless @sidebar == false %>
4
- <button data-controller="navbar" data-action="navbar#expandNavbar"
5
- class="btn btn-outline-light me-2 d-none d-<%= @breakpoint_navbar_expand %>-inline-block">
6
- <i class="bi <%= @navbar_chevron_class %>"></i>
7
- </button>
8
- <% end %>
9
- <% if @navbar.logo.present? %>
10
- <span class="ms-3">
11
- <%= render @navbar.logo %>
12
- </span>
13
- <% end %>
14
- <%= render partial: 'pg_layout/signed_in_links' %>
15
- <% @navbar.extensiones.each do |extension| %>
16
- <%= extension %>
17
- <% end %>
18
- <% unless @sidebar == false %>
19
- <button class="btn btn-outline-light d-inline-block
20
- d-<%= @breakpoint_navbar_expand %>-none"
21
- type="button"
22
- data-bs-toggle="offcanvas"
23
- data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
24
- <i class="bi bi-list"></i>
25
- </button>
26
- <% end %>
27
- </div>
28
- </nav>
29
- <div class="collapse" id="notifications-collapse" data-controller="notifications">
30
- <div id="notifications">
31
- <div id="notifications-inner">
32
- <% if @notifications&.any? %>
33
- <%= render NotificationComponent.with_collection(@notifications) if @notifications&.any? %>
34
- <% else %>
35
- <span class="text-light text-center">
36
- No hay notificaciones
37
- </span>
38
- <% end %>
39
- <div class="text-center">
40
- <button type="button" class="btn btn-link text-light btn-sm" data-bs-toggle="collapse" data-bs-target="#notifications-collapse">
41
- <i class="bi-chevron-up fs-3"></i>
42
- </button>
43
- </div>
44
- </div>
45
- </div>
46
- </div>
47
-
48
- <style type="text/css" media="(max-width: 767px)">
49
- .navbar .navbar-brand {
50
- visibility:visible!important;
51
- }
52
- </style>
@@ -1,24 +0,0 @@
1
- <div id="sidebar" class="<%= @navbar_opened_class %> flex-shrink-0 d-none d-<%= @breakpoint_navbar_expand %>-block">
2
- <div class="mt-1">
3
- <div class="m-3">
4
- <%= render @navbar.logo if @navbar.logo.present? %>
5
- </div>
6
- <ul class="list-unstyled ps-0 mt-5">
7
- <% @navbar.sidebar.each do |entry| %>
8
- <% next if @navbar.hide_entry?(entry) %>
9
-
10
- <li class="mb-1">
11
- <a
12
- href="<%= entry[:path] %>"
13
- class="
14
- d-inline-flex text-decoration-none pg--nav-button
15
- <%= @navbar.active_entry?(entry, request) ? 'active' : '' %>"
16
- <%= entry[:attributes] %>
17
- >
18
- <%= entry[:title] %>
19
- </a>
20
- </li>
21
- <% end %>
22
- </ul>
23
- </div>
24
- </div>
@@ -1,35 +0,0 @@
1
- <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
2
- <div class="offcanvas-header" data-bs-theme="dark">
3
- <h5 class="offcanvas-title" id="offcanvasExampleLabel"></h5>
4
- <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
5
- </div>
6
- <div class="offcanvas-body text-end">
7
- <% if user_signed_in? %>
8
- <span class="text-light pe-4 mt-4 d-inline-block"><%= Current.user %></span>
9
- <hr>
10
- <% end %>
11
- <ul class="list-unstyled mt-4">
12
- <% @navbar.sidebar.each do |entry| %>
13
- <% next if @navbar.hide_entry?(entry) %>
14
-
15
- <li>
16
- <a
17
- href="<%= entry[:path] %>"
18
- class="pg--nav-button pe-4 text-light <%= @navbar.active_entry?(entry, request) ? 'active' : '' %>"
19
- <%= entry[:attributes] %>
20
- >
21
- <%= entry[:title] %>
22
- </a>
23
- </li>
24
- <% end %>
25
- </ul>
26
- </div>
27
- </div>
28
- <style type="text/css">
29
- .offcanvas a {
30
- text-decoration: none;
31
- }
32
- .offcanvas li {
33
- xmargin-top: 0.75em;
34
- }
35
- </style>