pg_rails 7.6.2 → 7.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/pg_associable/app/helpers/pg_associable/form_builder_methods.rb +3 -0
  3. data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +29 -3
  4. data/pg_engine/app/components/bad_user_input_component.rb +1 -0
  5. data/pg_engine/app/components/inline_edit/inline_component.rb +27 -0
  6. data/pg_engine/app/components/inline_edit/inline_edit_component.html.slim +14 -0
  7. data/pg_engine/app/components/inline_edit/inline_edit_component.rb +13 -0
  8. data/pg_engine/app/components/inline_edit/inline_show_component.html.slim +8 -0
  9. data/pg_engine/app/components/inline_edit/inline_show_component.rb +2 -0
  10. data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +8 -4
  11. data/pg_engine/app/controllers/pg_engine/base_controller.rb +7 -16
  12. data/pg_engine/app/controllers/users/inline_edit_controller.rb +21 -0
  13. data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +2 -2
  14. data/pg_engine/app/helpers/pg_engine/index_helper.rb +1 -1
  15. data/pg_engine/app/lib/pg_form_builder.rb +18 -0
  16. data/pg_engine/app/models/pg_engine/base_record.rb +5 -1
  17. data/pg_engine/app/views/pg_engine/base/index.html.slim +2 -1
  18. data/pg_engine/config/initializers/zeitwerk.rb +2 -0
  19. data/pg_engine/config/routes.rb +4 -0
  20. data/pg_engine/config/simple_form/simple_form_bootstrap.rb +32 -2
  21. data/pg_engine/spec/controllers/pg_engine/base_controller_spec.rb +1 -16
  22. data/pg_engine/spec/requests/users/accounts_spec.rb +1 -2
  23. data/pg_engine/spec/requests/users/inline_edit_spec.rb +101 -0
  24. data/pg_layout/app/javascript/config/index.js +20 -20
  25. data/pg_layout/app/javascript/config/turbo_rails/index.js +4 -2
  26. data/pg_rails/lib/version.rb +1 -1
  27. data/pg_rails/scss/pg_rails.scss +4 -4
  28. data/pg_scaffold/lib/generators/pg_active_record/model/templates/model.rb +3 -0
  29. data/pg_scaffold/lib/generators/pg_slim/templates/_form.html.slim +1 -1
  30. metadata +9 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49f9abe4c2e4521dd99abe5a9220e3bece6ceb0e182c1a7d1fe252d836977bbf
4
- data.tar.gz: 105da76663a6b29c338c45cb0e46d2663b99c7463a91beb734771f34dd668319
3
+ metadata.gz: 558b69c5a93797c069002f3477d6ccc34b63b98fa4f1a37ddedcc4ab6010ef3b
4
+ data.tar.gz: a3cc4d53326372aaa5e7155b2d50cfdee3fc3d0814a81eee53ec3701814c3e23
5
5
  SHA512:
6
- metadata.gz: 344c3c89251c75d50c9ace0a1dac02d69ecb1d04e1392d330225c4496e7bfc5c24718cfb98c0c6843c24e5402d22b399d203cdbd6c3826c6f2cb9b8271b7da9e
7
- data.tar.gz: bb74de3073bb722ee4444a726306db6759c21e3ddc61e3f2a36e988b4ff688d72e31611d6168c2e936366d79c503924056da03ebd8f23dc7e07750cfb0ec2231
6
+ metadata.gz: 259c3f0cc7c935f4a5b9569a2cd33cb1cc60e71a1c5cc85118fb3190415ebad4d78065c641bbe0bdaf479639df1be0ef93ded0ad589313f7dd23011ecfa618d8
7
+ data.tar.gz: b0e0ad29958f836916d4469d43bd5f3c8797eb9e00a981694034c025158083f28a0ea32bce7057a957bd2d2898d75daf7905fc9e0facd2ec78677f0de06c3389
@@ -41,6 +41,7 @@ module PgAssociable
41
41
  user = Current.user
42
42
  puede_crear = !template.using_modal? && Pundit::PolicyFinder.new(klass).policy.new(user, klass).new?
43
43
  collection = Pundit::PolicyFinder.new(klass).scope.new(user, klass).resolve
44
+ collection = collection.kept if collection.respond_to?(:kept)
44
45
  [collection, puede_crear]
45
46
  end
46
47
 
@@ -50,9 +51,11 @@ module PgAssociable
50
51
  options.deep_merge!({ wrapper_html: { 'data-preload': collection.decorate.to_json } })
51
52
  end
52
53
  # TODO: usar una clase más precisa para el modal?
54
+ # quizás sea este el motivo por el cual no funciona el multimodal
53
55
  options.deep_merge!({ wrapper_html: { data: { controller: 'asociable',
54
56
  'asociable-modal-outlet': '.modal' } } })
55
57
  options[:as] = 'pg_associable'
58
+
56
59
  association atributo, options
57
60
  end
58
61
 
@@ -73,9 +73,10 @@ input[type=datetime-local], input[type=datetime] {
73
73
  display: flex;
74
74
  justify-content: flex-end;
75
75
  gap: 4px;
76
- }
77
- .listado .btn-sm {
78
- padding: 0em 0.3em;
76
+
77
+ .btn-sm {
78
+ padding: 0em 0.3em;
79
+ }
79
80
  }
80
81
 
81
82
  .list-group-item {
@@ -199,3 +200,28 @@ input[type=datetime-local], input[type=datetime] {
199
200
  }
200
201
  --fc-neutral-bg-color: none;
201
202
  }
203
+
204
+ // Inline edit
205
+
206
+ .inline-edit {
207
+ // text-decoration: underline;
208
+ // text-decoration-style: dotted;
209
+ // text-decoration-color: #262626;
210
+ border-bottom: 1px dotted #333;
211
+ padding-bottom: 1px;
212
+
213
+ a:hover {
214
+ i {
215
+ color: black;
216
+ }
217
+ }
218
+
219
+ input[type=text] {
220
+ min-width: 22em;
221
+ }
222
+
223
+ // To display correctly in tables with fixed witdh columns
224
+ .form-select {
225
+ width: initial;
226
+ }
227
+ }
@@ -1,3 +1,4 @@
1
+ # TODO: rename to WarningComponent or sth
1
2
  class BadUserInputComponent < BaseComponent
2
3
  def initialize(error_msg:)
3
4
  @error_msg = error_msg
@@ -0,0 +1,27 @@
1
+ class InlineComponent < ViewComponent::Base
2
+ def initialize(model, attribute)
3
+ @model = model
4
+ @attribute = attribute
5
+ @unsuffixed_attribute = unsuffixed(attribute)
6
+ @frame_id = dom_id(model, "#{attribute}_inline_edit")
7
+
8
+ super
9
+ end
10
+
11
+ def before_render
12
+ return unless controller.in_modal?
13
+
14
+ controller.instance_variable_set(:@using_modal, true)
15
+ end
16
+
17
+ SUFIJOS = %i[f text].freeze
18
+ def unsuffixed(attribute)
19
+ ret = attribute.to_s.dup
20
+
21
+ SUFIJOS.each do |sufijo|
22
+ ret.gsub!(/_#{sufijo}$/, '')
23
+ end
24
+
25
+ ret
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ = helpers.turbo_frame_tag(@frame_id, class: 'inline-edit')
2
+ = helpers.pg_form_for(@model, render_errors: false, wrapper_mappings: @wrapper_mappings,
3
+ html: { class: 'd-flex align-items-start gap-1' }) do |f|
4
+ = hidden_field_tag :inline_attribute, @attribute
5
+
6
+ = f.field @unsuffixed_attribute, label: false, html5: true
7
+
8
+ = button_tag class: 'btn btn-sm btn-primary',
9
+ data: { controller: 'tooltip', 'bs-title': 'Guardar' } do
10
+ i.bi.bi-check-lg
11
+ = link_to users_inline_show_path(model: @model.to_gid, attribute: @attribute),
12
+ class: 'btn btn-sm btn-secondary',
13
+ data: { controller: 'tooltip', 'bs-title': 'Cancelar' } do
14
+ i.bi.bi-x-lg
@@ -0,0 +1,13 @@
1
+ class InlineEditComponent < InlineComponent
2
+ def initialize(*)
3
+ @wrapper_mappings = {
4
+ string: :inline_form_grow,
5
+ pg_associable: :inline_form_control,
6
+ date: :inline_form_control,
7
+ datetime: :inline_form_control,
8
+ select: :inline_form_select
9
+ }
10
+
11
+ super
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ - if @model.class.inline_editable?(@unsuffixed_attribute) && helpers.policy(@model).edit?
2
+ = helpers.turbo_frame_tag(@frame_id, class: 'inline-edit')
3
+ = link_to users_inline_edit_path(model: @model.to_gid, attribute: @attribute),
4
+ class: 'text-body-tertiary', style: 'font-size: 0.8em' do
5
+ i.bi.bi-pencil
6
+ span.ms-1 = @model.decorate.send(@attribute)
7
+ - else
8
+ = @model.decorate.send(@attribute)
@@ -0,0 +1,2 @@
1
+ class InlineShowComponent < InlineComponent
2
+ end
@@ -257,7 +257,9 @@ module PgEngine
257
257
  if (@saved = object.save)
258
258
  respond_to do |format|
259
259
  format.html do
260
- if in_modal?
260
+ if params[:inline_attribute].present?
261
+ render InlineShowComponent.new(object, params[:inline_attribute]), layout: false
262
+ elsif in_modal?
261
263
  body = <<~HTML.html_safe
262
264
  <pg-event data-event-name="pg:record-updated" data-turbo-temporary
263
265
  data-response='#{object.decorate.to_json}'></pg-event>
@@ -272,6 +274,9 @@ module PgEngine
272
274
  render json: object.decorate.as_json
273
275
  end
274
276
  end
277
+ elsif params[:inline_attribute].present?
278
+ render InlineEditComponent.new(object, params[:inline_attribute]),
279
+ layout: false, status: :unprocessable_entity
275
280
  else
276
281
  add_breadcrumb instancia_modelo.decorate.to_s_short, instancia_modelo.decorate.target_object
277
282
  add_breadcrumb 'Modificando'
@@ -409,17 +414,16 @@ module PgEngine
409
414
  def set_instancia_modelo
410
415
  if action_name.in? %w[new create]
411
416
  self.instancia_modelo = clase_modelo.new(modelo_params)
417
+ authorize(instancia_modelo)
412
418
  if nested_id.present?
413
419
  instancia_modelo.send("#{nested_key}=", nested_id)
414
420
  end
415
421
  else
416
422
  self.instancia_modelo = buscar_instancia
417
-
423
+ authorize(instancia_modelo)
418
424
  instancia_modelo.assign_attributes(modelo_params) if action_name.in? %w[update]
419
425
  end
420
426
 
421
- authorize(instancia_modelo)
422
-
423
427
  # TODO: problema en create y update cuando falla la validacion
424
428
  # Reproducir el error antes de arreglarlo
425
429
  self.instancia_modelo = instancia_modelo.decorate if action_name.in? %w[show edit new]
@@ -216,22 +216,13 @@ module PgEngine
216
216
  end
217
217
 
218
218
  def not_authorized(_arg_required_for_active_admin)
219
- respond_to do |format|
220
- format.json do
221
- render json: { error: 'Acceso no autorizado' },
222
- status: :unprocessable_entity
223
- end
224
- # TODO: responder a turbo_stream
225
- format.html do
226
- if request.path == root_path
227
- # TODO!: renderear un 500.html y pg_err
228
- sign_out(Current.user) if Current.user.present?
229
- render plain: 'Acceso no autorizado', status: :unprocessable_entity
230
- else
231
- go_back('Acceso no autorizado')
232
- end
233
- end
234
- end
219
+ pg_warn <<~STRING
220
+ Acceso no autorizado.
221
+ User: #{Current.user.inspect}
222
+ Request: #{request.inspect}
223
+ STRING
224
+
225
+ render_my_component(BadUserInputComponent.new(error_msg: 'Acceso no autorizado'), :unauthorized)
235
226
  end
236
227
 
237
228
  def go_back(message = nil, type: :alert)
@@ -0,0 +1,21 @@
1
+ module Users
2
+ class InlineEditController < PgEngine.config.users_controller
3
+ before_action do
4
+ if current_turbo_frame.blank?
5
+ render_my_component(BadRequestComponent.new, :bad_request)
6
+ end
7
+ end
8
+
9
+ def edit
10
+ model = GlobalID::Locator.locate params[:model]
11
+ attribute = params[:attribute]
12
+ render InlineEditComponent.new(model, attribute), layout: false
13
+ end
14
+
15
+ def show
16
+ model = GlobalID::Locator.locate params[:model]
17
+ attribute = params[:attribute]
18
+ render InlineShowComponent.new(model, attribute), layout: false
19
+ end
20
+ end
21
+ end
@@ -118,8 +118,8 @@ module PgEngine
118
118
  end
119
119
  end
120
120
 
121
- def edit_object_url
122
- helpers.url_for([:edit, target_object].flatten)
121
+ def edit_object_url(**args)
122
+ helpers.url_for([:edit, target_object, **args].flatten)
123
123
  end
124
124
 
125
125
  def new_object_url
@@ -4,7 +4,7 @@ module PgEngine
4
4
  module IndexHelper
5
5
  def column_for(object, attribute)
6
6
  content_tag :td, **column_options_for(object, attribute) do
7
- object.send(attribute).to_s
7
+ render InlineShowComponent.new(object.object, attribute)
8
8
  end
9
9
  end
10
10
 
@@ -26,6 +26,24 @@ class PgFormBuilder < SimpleForm::FormBuilder
26
26
  super
27
27
  end
28
28
 
29
+ def field(attribute_name, options = {}, &)
30
+ model = convert_to_model(object)
31
+
32
+ if find_on_all_associations(model.class, attribute_name).present?
33
+ pg_associable(attribute_name, options)
34
+ else
35
+ input(attribute_name, options, &)
36
+ end
37
+ end
38
+
39
+ def find_on_all_associations(klass, campo)
40
+ return unless klass.respond_to? :reflect_on_all_associations
41
+
42
+ klass.reflect_on_all_associations.find do |a|
43
+ a.name == campo.to_sym
44
+ end
45
+ end
46
+
29
47
  def mensajes_de_error
30
48
  # TODO: quitar en before-cache?
31
49
  title = error_notification(message: mensaje, class: 'text-danger mb-2 error-title') if mensaje
@@ -16,7 +16,11 @@ module PgEngine
16
16
  class << self
17
17
  # This is a per class variable, all subclasses of BaseRecord inherit it
18
18
  # BUT **the values are independent between all of them**
19
- attr_accessor :default_modal
19
+ attr_accessor :default_modal, :inline_editable_fields
20
+
21
+ def inline_editable?(attribute)
22
+ inline_editable_fields.present? && inline_editable_fields.include?(attribute.to_sym)
23
+ end
20
24
  end
21
25
 
22
26
  # ransacker :search do |parent|
@@ -25,7 +25,8 @@ div
25
25
  th.text-nowrap style="font-size: 0.8em" = encabezado att, ordenable: true
26
26
  th.text-end
27
27
  - unless @export_link == false
28
- = @clase_modelo.new.decorate.export_link(request.url)
28
+ .actions-wrapper
29
+ = @clase_modelo.new.decorate.export_link(request.url)
29
30
  tbody
30
31
  - @collection.each do |object|
31
32
  - object = object.decorate
@@ -6,3 +6,5 @@ Rails.autoloaders.main.ignore(
6
6
  "#{PgEngine::Engine.root}/app/overrides",
7
7
  "#{PgEngine::Engine.root}/app/views"
8
8
  )
9
+
10
+ Rails.autoloaders.main.collapse("#{PgEngine::Engine.root}/app/components/inline_edit")
@@ -21,6 +21,10 @@ Rails.application.routes.draw do
21
21
  registrations: 'users/registrations'
22
22
  }, failure_app: PgEngine::DeviseFailureApp
23
23
  namespace :users, path: 'u' do
24
+ scope controller: 'inline_edit', path: 'inline', as: :inline do
25
+ get 'edit'
26
+ get 'show'
27
+ end
24
28
  get 'dashboard', to: 'dashboard#dashboard'
25
29
  post 'notifications/mark_as_seen', to: 'notifications#mark_as_seen'
26
30
  post 'notifications/mark_as_unseen', to: 'notifications#mark_as_unseen'
@@ -270,7 +270,7 @@ SimpleForm.setup do |config|
270
270
  # inline forms
271
271
  #
272
272
  # inline default_wrapper
273
- config.wrappers :inline_form, class: 'col-12' do |b|
273
+ config.wrappers :inline_form_grow, class: 'flex-grow-1' do |b|
274
274
  b.use :html5
275
275
  b.use :placeholder
276
276
  b.optional :maxlength
@@ -280,7 +280,37 @@ SimpleForm.setup do |config|
280
280
  b.optional :readonly
281
281
  b.use :label, class: 'visually-hidden'
282
282
 
283
- b.use :input, class: 'form-control', error_class: 'is-invalid'
283
+ b.use :input, class: 'form-control form-control-sm', error_class: 'is-invalid'
284
+ b.use :error, wrap_with: { class: 'invalid-feedback' }
285
+ b.optional :hint, wrap_with: { class: 'form-text' }
286
+ end
287
+
288
+ config.wrappers :inline_form_control, class: '' do |b|
289
+ b.use :html5
290
+ b.use :placeholder
291
+ b.optional :maxlength
292
+ b.optional :minlength
293
+ b.optional :pattern
294
+ b.optional :min_max
295
+ b.optional :readonly
296
+ b.use :label, class: 'visually-hidden'
297
+
298
+ b.use :input, class: 'form-control form-control-sm', error_class: 'is-invalid'
299
+ b.use :error, wrap_with: { class: 'invalid-feedback' }
300
+ b.optional :hint, wrap_with: { class: 'form-text' }
301
+ end
302
+
303
+ config.wrappers :inline_form_select, class: '' do |b|
304
+ b.use :html5
305
+ b.use :placeholder
306
+ b.optional :maxlength
307
+ b.optional :minlength
308
+ b.optional :pattern
309
+ b.optional :min_max
310
+ b.optional :readonly
311
+ b.use :label, class: 'visually-hidden'
312
+
313
+ b.use :input, class: 'form-select form-select-sm', error_class: 'is-invalid'
284
314
  b.use :error, wrap_with: { class: 'invalid-feedback' }
285
315
  b.optional :hint, wrap_with: { class: 'form-text' }
286
316
  end
@@ -84,22 +84,7 @@ describe DummyBaseController do
84
84
 
85
85
  it do
86
86
  subject
87
- expect(response).to redirect_to root_path
88
- expect(flash[:alert]).to eq 'Acceso no autorizado'
89
- expect(controller).to be_user_signed_in
90
- end
91
-
92
- context 'cuando ocurre en el root_path' do
93
- before do
94
- allow_any_instance_of(ActionController::TestRequest).to receive(:path).and_return(root_path)
95
- end
96
-
97
- it do
98
- subject
99
- expect(response).to have_http_status(:unprocessable_entity)
100
- expect(response.body).to eq 'Acceso no autorizado'
101
- expect(controller).not_to be_user_signed_in
102
- end
87
+ expect(response).to have_http_status(:unauthorized)
103
88
  end
104
89
  end
105
90
 
@@ -16,7 +16,6 @@ describe 'Users::AccountsController' do
16
16
  it 'denies foreign account' do
17
17
  other_account = create :account
18
18
  get "/u/cuentas/#{other_account.to_param}"
19
- expect(response).to have_http_status(:redirect)
20
- expect(flash[:alert]).to eq 'Acceso no autorizado'
19
+ expect(response).to have_http_status(:unauthorized)
21
20
  end
22
21
  end
@@ -0,0 +1,101 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'inline edit' do
4
+ before do
5
+ user = create :user
6
+ sign_in user
7
+ end
8
+
9
+ let(:cosa) { create :cosa }
10
+
11
+ describe '#show' do
12
+ subject do
13
+ get '/u/inline/show', params:, headers: { 'Turbo-Frame': turbo_frame_id }
14
+ end
15
+
16
+ let(:params) do
17
+ { model: cosa.to_gid.to_param, attribute: :nombre }
18
+ end
19
+
20
+ let(:turbo_frame_id) { 'turbo-frame' }
21
+
22
+ it do
23
+ subject
24
+ expect(response).to have_http_status(:ok)
25
+ expect(response.body).to include cosa.nombre
26
+ end
27
+
28
+ context 'when no turbo frame targetted' do
29
+ let(:turbo_frame_id) { nil }
30
+
31
+ it do
32
+ subject
33
+ expect(response).to have_http_status(:bad_request)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#edit' do
39
+ subject do
40
+ get '/u/inline/edit', params:, headers: { 'Turbo-Frame': turbo_frame_id }
41
+ end
42
+
43
+ let(:params) do
44
+ { model: cosa.to_gid.to_param, attribute: :nombre }
45
+ end
46
+
47
+ let(:turbo_frame_id) { 'turbo-frame' }
48
+
49
+ it do
50
+ subject
51
+ expect(response).to have_http_status(:ok)
52
+ expect(response.body).to include cosa.nombre
53
+ end
54
+
55
+ context 'when no turbo frame targetted' do
56
+ let(:turbo_frame_id) { nil }
57
+
58
+ it do
59
+ subject
60
+ expect(response).to have_http_status(:bad_request)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#update' do
66
+ subject do
67
+ patch "/u/cosas/#{cosa.to_param}", params:
68
+ end
69
+
70
+ let(:params) do
71
+ {
72
+ inline_attribute: 'nombre',
73
+ cosa: {
74
+ nombre:
75
+ }
76
+ }
77
+ end
78
+
79
+ let(:nombre) { 'otro' }
80
+
81
+ it do
82
+ subject
83
+ expect(response.body).to include 'turbo-frame'
84
+ expect(response).to have_http_status(:ok)
85
+ end
86
+
87
+ it do
88
+ expect { subject }.to change { cosa.reload.nombre }.to 'otro'
89
+ end
90
+
91
+ context 'when validation fails' do
92
+ let(:nombre) { nil }
93
+
94
+ it do
95
+ subject
96
+ expect(response.body).to include 'turbo-frame'
97
+ expect(response).to have_http_status(:unprocessable_entity)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -7,23 +7,23 @@ import './tooltips'
7
7
  import 'trix'
8
8
  import '@rails/actiontext'
9
9
 
10
- function bindListingClick () {
11
- document.body.onclick = (ev) => {
12
- if (ev.target.closest('a')) return
13
- if (ev.target.closest('.listado')) {
14
- const row = ev.target.closest('tr')
15
- if (row) {
16
- const show = row.querySelector('.bi-eye-fill')
17
- if (show) {
18
- const link = show.closest('a')
19
- if (link) {
20
- link.click()
21
- }
22
- }
23
- }
24
- }
25
- }
26
- }
27
- bindListingClick()
28
- document.addEventListener('turbo:load', bindListingClick)
29
- document.addEventListener('turbo:render', bindListingClick)
10
+ // function bindListingClick () {
11
+ // document.body.onclick = (ev) => {
12
+ // if (ev.target.closest('a')) return
13
+ // if (ev.target.closest('.listado')) {
14
+ // const row = ev.target.closest('tr')
15
+ // if (row) {
16
+ // const show = row.querySelector('.bi-eye-fill')
17
+ // if (show) {
18
+ // const link = show.closest('a')
19
+ // if (link) {
20
+ // link.click()
21
+ // }
22
+ // }
23
+ // }
24
+ // }
25
+ // }
26
+ // }
27
+ // bindListingClick()
28
+ // document.addEventListener('turbo:load', bindListingClick)
29
+ // document.addEventListener('turbo:render', bindListingClick)
@@ -23,8 +23,10 @@ document.addEventListener('turbo:before-cache', () => {
23
23
  })
24
24
  })
25
25
 
26
- document.addEventListener('turbo:frame-missing', (ev) => {
27
- Rollbar.error('Turbo Frame missing')
26
+ document.addEventListener('turbo:frame-missing', async (ev) => {
27
+ const text = await ev.detail.response.text()
28
+ Rollbar.error('turbo:frame-missing', text, ev.detail)
29
+ console.error('turbo:frame-missing', text, ev.detail)
28
30
  ev.preventDefault()
29
31
  const html = `
30
32
  <div>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.6.2'
4
+ VERSION = '7.6.4'
5
5
  end
@@ -89,7 +89,7 @@ $light-border-emphasis: shade-color($light, 60%);
89
89
  border: 1px solid $light-border-emphasis;
90
90
  }
91
91
 
92
- .listado tr:has(td:hover):has(.bi-eye-fill) td {
93
- background-color: #f2f2f2;
94
- cursor: pointer;
95
- }
92
+ // .listado tr:has(td:hover):has(.bi-eye-fill) td {
93
+ // background-color: #f2f2f2;
94
+ // cursor: pointer;
95
+ // }
@@ -15,6 +15,9 @@ class <%= class_name %> < <%= parent_class_name.classify %>
15
15
  <%- if options[:discard] -%>
16
16
  include Discard::Model
17
17
  <%- end -%>
18
+
19
+ self.default_modal = true
20
+ self.inline_editable_fields = %i[<%= attributes.map(&:name).join(' ') %>]
18
21
  <%- if attributes.any?(&:reference?) -%>
19
22
 
20
23
  <%- attributes.select(&:reference?).each do |attribute| -%>
@@ -3,7 +3,7 @@
3
3
  div style="max-width: 22em" data-controller="pg_form"
4
4
  = pg_form_for(@<%= singular_name %> || object) do |f|
5
5
  <%- attributes.each do |attribute| -%>
6
- = f.<%= attribute.reference? ? :pg_associable : :input %> :<%= attribute.name %>
6
+ = f.field :<%= attribute.name %>
7
7
  <%- end -%>
8
8
  .mt-2
9
9
  = f.button :submit
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.2
4
+ version: 7.6.4
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-09-30 00:00:00.000000000 Z
11
+ date: 2024-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -674,6 +674,11 @@ files:
674
674
  - pg_engine/app/components/date_selector_component.html.slim
675
675
  - pg_engine/app/components/date_selector_component.rb
676
676
  - pg_engine/app/components/flash_container_component.rb
677
+ - pg_engine/app/components/inline_edit/inline_component.rb
678
+ - pg_engine/app/components/inline_edit/inline_edit_component.html.slim
679
+ - pg_engine/app/components/inline_edit/inline_edit_component.rb
680
+ - pg_engine/app/components/inline_edit/inline_show_component.html.slim
681
+ - pg_engine/app/components/inline_edit/inline_show_component.rb
677
682
  - pg_engine/app/components/internal_error_component.rb
678
683
  - pg_engine/app/components/modal_component.html.slim
679
684
  - pg_engine/app/components/modal_component.rb
@@ -707,6 +712,7 @@ files:
707
712
  - pg_engine/app/controllers/users/confirmations_controller.rb
708
713
  - pg_engine/app/controllers/users/dashboard_controller.rb
709
714
  - pg_engine/app/controllers/users/date_jumper_controller.rb
715
+ - pg_engine/app/controllers/users/inline_edit_controller.rb
710
716
  - pg_engine/app/controllers/users/notifications_controller.rb
711
717
  - pg_engine/app/controllers/users/registrations_controller.rb
712
718
  - pg_engine/app/decorators/account_decorator.rb
@@ -902,6 +908,7 @@ files:
902
908
  - pg_engine/spec/requests/users/base_controller_spec.rb
903
909
  - pg_engine/spec/requests/users/dashboard_spec.rb
904
910
  - pg_engine/spec/requests/users/date_jumper_spec.rb
911
+ - pg_engine/spec/requests/users/inline_edit_spec.rb
905
912
  - pg_engine/spec/requests/users/registrations_spec.rb
906
913
  - pg_engine/spec/requests/users/switcher_spec.rb
907
914
  - pg_engine/spec/system/alerts_spec.rb