pg_rails 7.2.0 → 7.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/pg_engine/app/assets/stylesheets/pg_rails_b5.scss +7 -2
  3. data/pg_engine/app/components/bad_user_input_component.rb +16 -0
  4. data/pg_engine/app/components/date_selector_component.html.slim +14 -0
  5. data/pg_engine/app/components/date_selector_component.rb +19 -0
  6. data/pg_engine/app/controllers/pg_engine/base_controller.rb +5 -0
  7. data/pg_engine/app/controllers/users/date_jumper_controller.rb +50 -0
  8. data/pg_engine/app/controllers/users/notifications_controller.rb +1 -1
  9. data/pg_engine/app/inputs/pg_engine/fecha_input.rb +25 -1
  10. data/pg_engine/app/lib/pg_engine/date_jumper.rb +74 -0
  11. data/pg_engine/app/views/pg_engine/base/index.html.slim +1 -1
  12. data/pg_engine/config/routes.rb +1 -0
  13. data/pg_engine/config/simple_form/simple_form_bootstrap.rb +0 -16
  14. data/pg_engine/lib/pg_engine/configuracion.rb +11 -2
  15. data/pg_engine/lib/pg_engine/error.rb +3 -0
  16. data/pg_engine/lib/pg_engine.rb +1 -0
  17. data/pg_engine/spec/components/previews/alert_component_preview/list_group.html.slim +12 -0
  18. data/pg_engine/spec/components/previews/alert_component_preview.rb +2 -0
  19. data/pg_engine/spec/lib/pg_engine/date_jumper_spec.rb +55 -0
  20. data/pg_engine/spec/requests/users/date_jumper_spec.rb +148 -0
  21. data/pg_engine/spec/system/date_selector_spec.rb +35 -0
  22. data/pg_layout/app/javascript/controllers/date_selector_controller.js +69 -0
  23. data/pg_layout/app/javascript/controllers/index.js +6 -0
  24. data/pg_layout/app/javascript/controllers/popover_controller.js +10 -0
  25. data/pg_layout/app/javascript/controllers/popover_toggler_controller.js +29 -0
  26. data/pg_rails/lib/version.rb +1 -1
  27. metadata +28 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 682cb0d34f5b9fd5b90c73dab52290c14f5a916727e2ad42ff93931529e9a0ad
4
- data.tar.gz: 5d5403222c95b985435129b7a6c089bd0923c752805a1c497dc20ea9278e2655
3
+ metadata.gz: 20cb7ade648f78aa73ed631d9732326edc5a251a36141d054084366d9a6b9859
4
+ data.tar.gz: 38c923c5650e20ecb6be91b304ec3014cbd189976b254500275f5d2bf77ea9a0
5
5
  SHA512:
6
- metadata.gz: 5103978d4427bda089782ab1930ca058e2f759c0e17ab7d7e3326b126b8e7803cb7903ddc7e167ff4e866c0a58b57b73ac87b082cffae20cdd0c63cd8781caca
7
- data.tar.gz: 17816668dcb26c86e1b5abc881276b25eea748a8dfe28196dd1d67e70fc15072408ffdbd98b173cebdc6502e47de79f35a7f7a32551ed9d00c71b3bd4639e3ba
6
+ metadata.gz: 156c1e465ab38406145f7d3bddf65fa0e40bf28a16109c15eb41f623735032dd23f7ddfb4a3341abbe8167ffd065082aef10945c8181c38bb01c4c368aa1853e
7
+ data.tar.gz: 7691712c1641cceb9ed53b6740ad9650844b69056c8433c4b65eb149cc9014ebce8870583306ebe7ed55c23209ec6b762b1a6961225fd65281aa5ddeec133dad
@@ -74,8 +74,8 @@ input[type=datetime-local], input[type=datetime] {
74
74
  }
75
75
 
76
76
  .list-group-item {
77
- --bs-list-group-item-padding-y: 0px;
78
- --bs-list-group-item-padding-x: 0.3rem;
77
+ --bs-list-group-item-padding-y: 0.3em;
78
+ --bs-list-group-item-padding-x: 1em;
79
79
  }
80
80
 
81
81
  // FILTROS
@@ -103,6 +103,11 @@ input[type=datetime-local], input[type=datetime] {
103
103
  width: min-content;
104
104
  }
105
105
 
106
+ // Popover
107
+ .modal-content, .popover {
108
+ box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, 0.3);
109
+ }
110
+
106
111
  // Modal
107
112
  .modal-content {
108
113
  box-shadow: 15px 15px 9px 0px rgba(0, 0, 0, 0.6);
@@ -0,0 +1,16 @@
1
+ class BadUserInputComponent < BaseComponent
2
+ def initialize(error_msg:)
3
+ @error_msg = error_msg
4
+ super
5
+ end
6
+
7
+ def alert_type
8
+ :warning
9
+ end
10
+
11
+ erb_template <<~ERB
12
+ <div>
13
+ <%= @error_msg %>
14
+ </div>
15
+ ERB
16
+ end
@@ -0,0 +1,14 @@
1
+ .d-flex.flex-column.align-items-start.gap-2[
2
+ data-controller="date-selector" data-field-id="#{@field_id}"
3
+ ]
4
+ = number_field_tag 'quantity', nil,
5
+ placeholder: 'Cantidad', class: 'form-control form-control-sm'
6
+ = select_tag 'type', options_for_select(@types),
7
+ class: 'form-select form-select-sm'
8
+ = select_tag 'direction', options_for_select(@directions),
9
+ class: 'form-select form-select-sm'
10
+ .d-flex.justify-content-between.w-100
11
+ = button_tag 'Aceptar', class: 'btn btn-sm btn-primary',
12
+ 'data-action': 'date-selector#submit'
13
+ = button_tag 'Hoy', class: 'btn btn-sm btn-link float-end',
14
+ 'data-action': 'date-selector#today'
@@ -0,0 +1,19 @@
1
+ class DateSelectorComponent < ViewComponent::Base
2
+ def initialize(field_id)
3
+ @field_id = field_id
4
+
5
+ @types = [
6
+ ['Días corridos (L a D)', 'calendar_days'],
7
+ ['Días hábiles (L a V)', 'business_days'],
8
+ ['Días hábiles no feriados', 'business_days_excluding_holidays'],
9
+ ['Semanas', 'weeks'],
10
+ ['Meses', 'months']
11
+ ]
12
+
13
+ @directions = [
14
+ ['Hacia adelante', 'forward'],
15
+ ['Hacia atrás', 'backward']
16
+ ]
17
+ super
18
+ end
19
+ end
@@ -23,6 +23,7 @@ module PgEngine
23
23
  protect_from_forgery with: :exception
24
24
 
25
25
  rescue_from StandardError, with: :internal_error
26
+ rescue_from PgEngine::BadUserInput, with: :bad_user_input
26
27
  rescue_from ActionController::InvalidAuthenticityToken,
27
28
  with: :invalid_authenticity_token
28
29
 
@@ -32,6 +33,10 @@ module PgEngine
32
33
  redirect_to e.url
33
34
  end
34
35
 
36
+ def bad_user_input(error)
37
+ render_my_component(BadUserInputComponent.new(error_msg: error.message), :bad_request)
38
+ end
39
+
35
40
  def internal_error(error)
36
41
  pg_err error
37
42
 
@@ -0,0 +1,50 @@
1
+ module Users
2
+ class DateJumperController < PgEngine.config.users_controller
3
+ before_action only: :jump do
4
+ if params[:quantity].blank?
5
+ raise PgEngine::BadUserInput, 'Cantidad incorrecta'
6
+ end
7
+ end
8
+
9
+ def jump
10
+ start_date = Date.parse(params[:start_date])
11
+ quantity = params[:quantity].to_i
12
+
13
+ date =
14
+ case params[:type]
15
+ when 'calendar_days'
16
+ start_date + (multiplier * quantity.days)
17
+ when 'business_days', 'business_days_excluding_holidays'
18
+ resolve_business_days(start_date, quantity)
19
+ when 'weeks'
20
+ start_date + (multiplier * quantity.weeks)
21
+ when 'months'
22
+ start_date + (multiplier * quantity.months)
23
+ else
24
+ # :nocov:
25
+ raise PgEngine::Error, 'type no soportado'
26
+ # :nocov:
27
+ end
28
+
29
+ render json: { date: }
30
+ end
31
+
32
+ private
33
+
34
+ def resolve_business_days(start_date, quantity)
35
+ exclude_holidays = params[:type].include?('excluding_holidays')
36
+ options = { direction: params[:direction], exclude_holidays: }
37
+
38
+ PgEngine::DateJumper.new(start_date)
39
+ .business_days(quantity, **options)
40
+ end
41
+
42
+ def multiplier
43
+ if params[:direction] == 'forward'
44
+ 1
45
+ else
46
+ -1
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,5 +1,5 @@
1
1
  module Users
2
- class NotificationsController < ApplicationController
2
+ class NotificationsController < PgEngine.config.users_controller
3
3
  def mark_as_unseen
4
4
  notification = Noticed::Notification.find(params[:id])
5
5
  notification.mark_as_unseen!
@@ -10,11 +10,35 @@ module PgEngine
10
10
  else
11
11
  object.public_send(attribute_name)
12
12
  end
13
+
13
14
  @input_type = 'date'
14
15
 
15
16
  options = merge_wrapper_options({ value:, class: '', autocomplete: 'off' },
16
17
  wrapper_options)
17
- super(options)
18
+ if input_options[:date_selector]
19
+ content_tag 'div', class: 'd-flex align-items-center' do
20
+ super(options) + date_selector
21
+ end
22
+ else
23
+ super(options)
24
+ end
25
+ end
26
+
27
+ include ActionView::Helpers::FormTagHelper
28
+ def date_selector
29
+ field_id = @builder.field_id(attribute_name)
30
+ html = DateSelectorComponent.new(field_id).render_in(@builder.template)
31
+ # tabindex required: https://getbootstrap.com/docs/5.3/components/popovers/#dismiss-on-next-click
32
+ link_to 'javascript:void(0)',
33
+ class: 'btn btn-link', tabindex: 0,
34
+ data: {
35
+ controller: 'popover-toggler',
36
+ 'bs-html': true,
37
+ 'bs-title': 'Cambiar la fecha',
38
+ 'bs-content': html
39
+ } do
40
+ '<i class="bi bi-magic"></i>'.html_safe
41
+ end
18
42
  end
19
43
  end
20
44
  end
@@ -0,0 +1,74 @@
1
+ module PgEngine
2
+ class DateJumper
3
+ def initialize(start_date)
4
+ @start_date = start_date
5
+ end
6
+
7
+ def business_days(days, direction:, exclude_holidays: false)
8
+ case direction
9
+ when :forward, 'forward'
10
+ business_forward(days, exclude_holidays:)
11
+ when :backward, 'backward'
12
+ business_backward(days, exclude_holidays:)
13
+ else
14
+ # :nocov:
15
+ raise PgEngine::Error, 'direction not supported'
16
+ # :nocov:
17
+ end
18
+ end
19
+
20
+ def business_forward(days, exclude_holidays: false)
21
+ days.times.inject(@start_date) do |acc, _|
22
+ if exclude_holidays
23
+ find_excluding_holidays(method: :next_business_day, from: acc)
24
+ else
25
+ next_business_day(acc)
26
+ end
27
+ end
28
+ end
29
+
30
+ def business_backward(days, exclude_holidays: false)
31
+ days.times.inject(@start_date) do |acc, _|
32
+ if exclude_holidays
33
+ find_excluding_holidays(method: :prev_business_day, from: acc)
34
+ else
35
+ prev_business_day(acc)
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def find_excluding_holidays(method:, from:)
43
+ aux = from
44
+ safe_counter = 0
45
+ loop do
46
+ safe_counter += 1
47
+ aux = send(method, aux)
48
+ if safe_counter > 10
49
+ # :nocov:
50
+ raise 'las cosas'
51
+ # :nocov:
52
+ end
53
+ break unless Holidays.on(aux, :ar).any?
54
+ end
55
+ aux
56
+ end
57
+
58
+ def next_business_day(date)
59
+ if date.wday.in? [0, 5, 6]
60
+ date.next_occurring(:monday)
61
+ else
62
+ date.advance(days: 1)
63
+ end
64
+ end
65
+
66
+ def prev_business_day(date)
67
+ if date.wday.in? [0, 1, 6]
68
+ date.prev_occurring(:friday)
69
+ else
70
+ date.advance(days: -1)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -43,7 +43,7 @@ div
43
43
  - available_page_sizes.each do |page_size|
44
44
  = link_to page_size,
45
45
  namespaced_path(@clase_modelo, page_size:),
46
- class: "list-group-item #{'active' if current_page_size == page_size}"
46
+ class: "list-group-item py-0 px-1 #{'active' if current_page_size == page_size}"
47
47
  - elsif @records_filtered
48
48
  - i18n_key = "#{controller_key}.#{action_name}.index.empty_but_filtered"
49
49
  p.m-3
@@ -20,6 +20,7 @@ Rails.application.routes.draw do
20
20
  namespace :users, path: 'u' do
21
21
  post 'notifications/mark_as_seen', to: 'notifications#mark_as_seen'
22
22
  post 'notifications/mark_as_unseen', to: 'notifications#mark_as_unseen'
23
+ get 'date_jumper/jump'
23
24
  end
24
25
  namespace :admin, path: 'a' do
25
26
  pg_resource(:emails)
@@ -69,22 +69,6 @@ SimpleForm.setup do |config|
69
69
  b.use :hint, wrap_with: { class: 'form-text' }
70
70
  end
71
71
 
72
- config.wrappers :vertical_form_inline_wrap, class: 'mb-3' do |b|
73
- b.use :html5
74
- b.use :placeholder
75
- b.optional :maxlength
76
- b.optional :minlength
77
- b.optional :pattern
78
- b.optional :min_max
79
- b.optional :readonly
80
- b.use :label, class: 'form-label d-block'
81
- b.wrapper class: 'd-inline-block' do |bb|
82
- bb.use :input, class: 'form-control', error_class: 'is-invalid'
83
- end
84
- b.use :error, wrap_with: { class: 'invalid-feedback' }
85
- b.use :hint, wrap_with: { class: 'form-text' }
86
- end
87
-
88
72
  config.wrappers :vertical_no_margin_control, &control_wrapper
89
73
 
90
74
  config.wrappers :vertical_no_margin_select, &select_wrapper
@@ -4,8 +4,11 @@
4
4
 
5
5
  module PgEngine
6
6
  class Configuracion
7
- attr_accessor :sistema_iconos, :clase_botones_chicos, :boton_destroy, :boton_edit,
8
- :boton_show, :boton_light, :icono_destroy, :icono_edit, :icono_show, :boton_export, :bootstrap_version
7
+ attr_accessor :sistema_iconos, :clase_botones_chicos,
8
+ :boton_destroy, :boton_edit, :boton_show,
9
+ :boton_light, :icono_destroy, :icono_edit,
10
+ :icono_show, :boton_export, :bootstrap_version,
11
+ :users_controller
9
12
 
10
13
  def initialize
11
14
  @sistema_iconos = 'bi'
@@ -19,6 +22,12 @@ module PgEngine
19
22
  @icono_edit = 'pencil'
20
23
  @icono_show = 'eye-fill'
21
24
  @bootstrap_version = 5
25
+
26
+ if defined? UsersController
27
+ @users_controller = UsersController
28
+ elsif defined? FrontendController
29
+ @users_controller = FrontendController
30
+ end
22
31
  end
23
32
  end
24
33
  end
@@ -2,6 +2,9 @@ module PgEngine
2
2
  class Error < StandardError
3
3
  end
4
4
 
5
+ class BadUserInput < Error
6
+ end
7
+
5
8
  class PageNotFoundError < Error
6
9
  end
7
10
  end
@@ -53,6 +53,7 @@ require 'pg_search'
53
53
  require 'view_component'
54
54
  require 'noticed'
55
55
  require 'ransack_memory'
56
+ require 'holidays'
56
57
 
57
58
  if Rails.env.local?
58
59
  require 'letter_opener'
@@ -0,0 +1,12 @@
1
+ h1 List groups
2
+
3
+ ul.list-group
4
+ li.list-group-item un ítem
5
+ li.list-group-item otro ítem
6
+
7
+ br
8
+ br
9
+
10
+ ul.list-group.list-group-horizontal
11
+ li.list-group-item un ítem
12
+ li.list-group-item otro ítem
@@ -9,4 +9,6 @@ class AlertComponentPreview < ViewComponent::Preview
9
9
  def colours; end
10
10
 
11
11
  def tooltips; end
12
+
13
+ def list_group; end
12
14
  end
@@ -0,0 +1,55 @@
1
+ require 'rails_helper'
2
+
3
+ describe PgEngine::DateJumper do
4
+ subject do
5
+ jumper.send(method, days, exclude_holidays:)
6
+ end
7
+
8
+ let(:method) { self.class.metadata[:method] }
9
+ let(:jumper) { described_class.new(start_date) }
10
+ let(:start_date) { Date.new(2024, 8, 16) }
11
+ let(:days) { 5 }
12
+ let(:exclude_holidays) { false }
13
+
14
+ def fake_holiday(date)
15
+ allow(Holidays).to receive(:on).and_call_original
16
+ allow(Holidays).to receive(:on).with(date, anything)
17
+ .and_return([:some_fake_holiday])
18
+ end
19
+
20
+ describe 'business_forward', method: 'business_forward' do
21
+ it do
22
+ expect(subject).to eq Date.new(2024, 8, 23)
23
+ end
24
+
25
+ context 'excluding holidays' do
26
+ before do
27
+ fake_holiday(Date.new(2024, 8, 23))
28
+ end
29
+
30
+ let(:exclude_holidays) { true }
31
+
32
+ it do
33
+ expect(subject).to eq Date.new(2024, 8, 26)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe 'business_forward', method: 'business_backward' do
39
+ it do
40
+ expect(subject).to eq Date.new(2024, 8, 9)
41
+ end
42
+
43
+ context 'excluding holidays' do
44
+ before do
45
+ fake_holiday(Date.new(2024, 8, 14))
46
+ end
47
+
48
+ let(:exclude_holidays) { true }
49
+
50
+ it do
51
+ expect(subject).to eq Date.new(2024, 8, 8)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,148 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe 'Users::DateJumpers' do
4
+ before do
5
+ user = create :user
6
+ sign_in user
7
+ end
8
+
9
+ describe 'GET /jump' do
10
+ before do
11
+ stubs if defined? stubs
12
+ get '/u/date_jumper/jump', params: {
13
+ start_date:,
14
+ quantity:,
15
+ type:,
16
+ direction:
17
+ }, headers: { accept: 'application/json' }
18
+ end
19
+
20
+ let(:start_date) { Date.new(2024, 8, 16) }
21
+ let(:quantity) { 5 }
22
+
23
+ context 'when quantity is blank' do
24
+ let(:quantity) { '' }
25
+ let(:type) { 'calendar_days' }
26
+ let(:direction) { 'forward' }
27
+
28
+ it do
29
+ expect(response).to have_http_status(:bad_request)
30
+ expect(JSON.parse(response.body)['html']).to include 'Cantidad incorrecta'
31
+ end
32
+ end
33
+
34
+ context 'when moving calendar days' do
35
+ let(:type) { 'calendar_days' }
36
+
37
+ context 'forward' do
38
+ let(:direction) { 'forward' }
39
+
40
+ it do
41
+ expect(JSON.parse(response.body)['date']).to eq '2024-08-21'
42
+ end
43
+ end
44
+
45
+ context 'backward' do
46
+ let(:direction) { 'backward' }
47
+
48
+ it do
49
+ expect(JSON.parse(response.body)['date']).to eq '2024-08-11'
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'when moving business days' do
55
+ let(:type) { 'business_days' }
56
+
57
+ context 'forward' do
58
+ let(:direction) { 'forward' }
59
+
60
+ it do
61
+ expect(JSON.parse(response.body)['date']).to eq '2024-08-23'
62
+ end
63
+ end
64
+
65
+ context 'backward' do
66
+ let(:direction) { 'backward' }
67
+
68
+ it do
69
+ expect(JSON.parse(response.body)['date']).to eq '2024-08-09'
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'when moving business days excluding holidays' do
75
+ def fake_holiday(date)
76
+ allow(Holidays).to receive(:on).and_call_original
77
+ allow(Holidays).to receive(:on).with(date, anything)
78
+ .and_return([:some_fake_holiday])
79
+ end
80
+
81
+ let(:type) { 'business_days_excluding_holidays' }
82
+
83
+ context 'forward' do
84
+ let(:stubs) do
85
+ fake_holiday(Date.new(2024, 8, 23))
86
+ end
87
+
88
+ let(:direction) { 'forward' }
89
+
90
+ it do
91
+ expect(JSON.parse(response.body)['date']).to eq '2024-08-26'
92
+ end
93
+ end
94
+
95
+ context 'backward' do
96
+ let(:stubs) do
97
+ fake_holiday(Date.new(2024, 8, 14))
98
+ end
99
+
100
+ let(:direction) { 'backward' }
101
+
102
+ it do
103
+ expect(JSON.parse(response.body)['date']).to eq '2024-08-08'
104
+ end
105
+ end
106
+ end
107
+
108
+ context 'when moving weeks' do
109
+ let(:type) { 'weeks' }
110
+
111
+ context 'forward' do
112
+ let(:direction) { 'forward' }
113
+
114
+ it do
115
+ expect(JSON.parse(response.body)['date']).to eq '2024-09-20'
116
+ end
117
+ end
118
+
119
+ context 'backward' do
120
+ let(:direction) { 'backward' }
121
+
122
+ it do
123
+ expect(JSON.parse(response.body)['date']).to eq '2024-07-12'
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'when moving months' do
129
+ let(:type) { 'months' }
130
+
131
+ context 'forward' do
132
+ let(:direction) { 'forward' }
133
+
134
+ it do
135
+ expect(JSON.parse(response.body)['date']).to eq '2025-01-16'
136
+ end
137
+ end
138
+
139
+ context 'backward' do
140
+ let(:direction) { 'backward' }
141
+
142
+ it do
143
+ expect(JSON.parse(response.body)['date']).to eq '2024-03-16'
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,35 @@
1
+ # Initially generated with PgRails::SystemSpecGenerator
2
+ # https://github.com/martin-rosso/pg_rails
3
+
4
+ require 'rails_helper'
5
+
6
+ # By default uses selenium_chrome_headless_iphone driver
7
+ # run with DRIVER environment variable to override, eg:
8
+ #
9
+ # DRIVER=selenium rspec
10
+ describe 'Date selector' do
11
+ subject(:visitar) do
12
+ visit edit_admin_categoria_de_cosa_path(categoria_de_cosa)
13
+ end
14
+
15
+ let(:logged_user) { create :user }
16
+ let(:account) { logged_user.current_account }
17
+ let(:categoria_de_cosa) { create :categoria_de_cosa, fecha: }
18
+ let(:fecha) { Date.new(2024, 8, 12) }
19
+
20
+ before do
21
+ login_as logged_user
22
+ end
23
+
24
+ describe 'jump N days' do
25
+ it do
26
+ visitar
27
+ find('.categoria_de_cosa_fecha [data-controller="popover-toggler"]').click
28
+ fill_in 'quantity', with: '3'
29
+ select 'Días hábiles (L a V)'
30
+ click_on 'Aceptar'
31
+ click_on 'Actualizar Categoría de cosa'
32
+ expect(page).to have_text '15/08/2024'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,69 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import { flashMessage } from '../utils/utils'
3
+ import { get } from '@rails/request.js'
4
+ import Rollbar from 'rollbar'
5
+
6
+ export default class extends Controller {
7
+ today () {
8
+ const fechaEl = document.getElementById(this.element.dataset.fieldId)
9
+ let today = new Date()
10
+ const dd = String(today.getDate()).padStart(2, '0')
11
+ const mm = String(today.getMonth() + 1).padStart(2, '0') // January is 0!
12
+ const yyyy = today.getFullYear()
13
+
14
+ today = yyyy + '-' + mm + '-' + dd
15
+ fechaEl.value = today
16
+ return fechaEl.value
17
+ }
18
+
19
+ closePopover () {
20
+ const popover = this.element.closest('.popover')
21
+ this.application.getControllerForElementAndIdentifier(popover, 'popover').close()
22
+ }
23
+
24
+ async submit () {
25
+ const fechaEl = document.getElementById(this.element.dataset.fieldId)
26
+ let startDate = fechaEl.value
27
+ if (!startDate) {
28
+ startDate = this.today()
29
+ }
30
+
31
+ const quantity = this.element.querySelector('input[name=quantity]').value
32
+ if (!quantity) {
33
+ this.closePopover()
34
+ return
35
+ }
36
+ const type = this.element.querySelector('select[name=type]').value
37
+ const direction = this.element.querySelector('select[name=direction]').value
38
+ // console.log(quantity, type, direction)
39
+ this.element.querySelector('button').setAttribute('disabled', 'true')
40
+ // let input = this
41
+ const response = await get('/u/date_jumper/jump', {
42
+ query: {
43
+ start_date: startDate,
44
+ quantity,
45
+ type,
46
+ direction
47
+ },
48
+ responseKind: 'json'
49
+ })
50
+
51
+ if (response.ok) {
52
+ const json = await response.json
53
+ fechaEl.value = json.date
54
+ this.element.querySelector('button').removeAttribute('disabled')
55
+ this.closePopover()
56
+ } else {
57
+ let message = 'Hubo un error'
58
+ try {
59
+ const json = await response.json
60
+ message = json.html || 'Hubo un error'
61
+ } catch {
62
+ // JSON parser error
63
+ }
64
+ flashMessage(message, 'warning', true)
65
+ this.element.querySelector('button').removeAttribute('disabled')
66
+ Rollbar.error('date jumper error', json)
67
+ }
68
+ }
69
+ }
@@ -11,6 +11,9 @@ import NotificationsController from './notifications_controller'
11
11
  import SelectizeController from './selectize_controller'
12
12
  import ThemeController from './theme_controller'
13
13
  import TooltipController from './tooltip_controller'
14
+ import PopoverController from './popover_controller'
15
+ import PopoverTogglerController from './popover_toggler_controller'
16
+ import DateSelectorController from './date_selector_controller'
14
17
 
15
18
  application.register('navbar', NavbarController)
16
19
  application.register('nested', NestedController)
@@ -23,5 +26,8 @@ application.register('notifications', NotificationsController)
23
26
  application.register('selectize', SelectizeController)
24
27
  application.register('theme', ThemeController)
25
28
  application.register('tooltip', TooltipController)
29
+ application.register('popover', PopoverController)
30
+ application.register('popover-toggler', PopoverTogglerController)
31
+ application.register('date-selector', DateSelectorController)
26
32
 
27
33
  // TODO: testear con capybara todo lo que se pueda
@@ -0,0 +1,10 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import * as bootstrap from 'bootstrap'
3
+
4
+ export default class extends Controller {
5
+ close () {
6
+ const toggler = document.querySelector('[aria-describedby="' + this.element.id + '"]')
7
+ const instance = bootstrap.Popover.getInstance(toggler)
8
+ instance.hide()
9
+ }
10
+ }
@@ -0,0 +1,29 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import * as bootstrap from 'bootstrap'
3
+
4
+ export default class extends Controller {
5
+ popover = null
6
+
7
+ connect () {
8
+ this.popover = new bootstrap.Popover(this.element, {
9
+ // WARNING: don't use for user input html
10
+ sanitize: false,
11
+ template: `
12
+ <div class="popover" role="tooltip" data-controller="popover">
13
+ <div class="popover-arrow"></div>
14
+ <div class="popover-header"></div>
15
+ <button type="button" class="btn-close position-absolute" data-action="popover#close" style="top: 1em; right: 1em;" aria-label="Close"></button>
16
+ <div class="popover-body">
17
+ </div>
18
+ </div>
19
+ `,
20
+ container: 'body'
21
+ })
22
+ }
23
+
24
+ disconnect () {
25
+ if (this.popover) {
26
+ this.popover.dispose()
27
+ }
28
+ }
29
+ }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.2.0'
4
+ VERSION = '7.2.2'
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.2.0
4
+ version: 7.2.2
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-08-14 00:00:00.000000000 Z
11
+ date: 2024-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -584,6 +584,20 @@ dependencies:
584
584
  - - "~>"
585
585
  - !ruby/object:Gem::Version
586
586
  version: '2.3'
587
+ - !ruby/object:Gem::Dependency
588
+ name: holidays
589
+ requirement: !ruby/object:Gem::Requirement
590
+ requirements:
591
+ - - "~>"
592
+ - !ruby/object:Gem::Version
593
+ version: '8.8'
594
+ type: :runtime
595
+ prerelease: false
596
+ version_requirements: !ruby/object:Gem::Requirement
597
+ requirements:
598
+ - - "~>"
599
+ - !ruby/object:Gem::Version
600
+ version: '8.8'
587
601
  description: Rails goodies.
588
602
  email:
589
603
  - mrosso10@gmail.com
@@ -625,7 +639,10 @@ files:
625
639
  - pg_engine/app/components/alert_component.html.slim
626
640
  - pg_engine/app/components/alert_component.rb
627
641
  - pg_engine/app/components/bad_request_component.rb
642
+ - pg_engine/app/components/bad_user_input_component.rb
628
643
  - pg_engine/app/components/base_component.rb
644
+ - pg_engine/app/components/date_selector_component.html.slim
645
+ - pg_engine/app/components/date_selector_component.rb
629
646
  - pg_engine/app/components/flash_container_component.rb
630
647
  - pg_engine/app/components/internal_error_component.rb
631
648
  - pg_engine/app/components/notification_component.rb
@@ -649,6 +666,7 @@ files:
649
666
  - pg_engine/app/controllers/public/mensaje_contactos_controller.rb
650
667
  - pg_engine/app/controllers/public/webhooks_controller.rb
651
668
  - pg_engine/app/controllers/users/confirmations_controller.rb
669
+ - pg_engine/app/controllers/users/date_jumper_controller.rb
652
670
  - pg_engine/app/controllers/users/notifications_controller.rb
653
671
  - pg_engine/app/controllers/users/registrations_controller.rb
654
672
  - pg_engine/app/decorators/account_decorator.rb
@@ -668,6 +686,7 @@ files:
668
686
  - pg_engine/app/helpers/pg_engine/print_helper.rb
669
687
  - pg_engine/app/helpers/pg_engine/route_helper.rb
670
688
  - pg_engine/app/inputs/pg_engine/fecha_input.rb
689
+ - pg_engine/app/lib/pg_engine/date_jumper.rb
671
690
  - pg_engine/app/lib/pg_engine/devise_failure_app.rb
672
691
  - pg_engine/app/lib/pg_engine/error_helper.rb
673
692
  - pg_engine/app/lib/pg_engine/filtros_builder.rb
@@ -781,6 +800,7 @@ files:
781
800
  - pg_engine/spec/components/previews/alert_component_preview/colours.html.slim
782
801
  - pg_engine/spec/components/previews/alert_component_preview/default.html.slim
783
802
  - pg_engine/spec/components/previews/alert_component_preview/dismisible.html.slim
803
+ - pg_engine/spec/components/previews/alert_component_preview/list_group.html.slim
784
804
  - pg_engine/spec/components/previews/alert_component_preview/tooltips.html.slim
785
805
  - pg_engine/spec/components/previews/internal_error_preview.rb
786
806
  - pg_engine/spec/components/previews/internal_error_preview/default.html.slim
@@ -806,6 +826,7 @@ files:
806
826
  - pg_engine/spec/fixtures/test.pdf
807
827
  - pg_engine/spec/helpers/pg_engine/pg_rails_helper_spec.rb
808
828
  - pg_engine/spec/helpers/pg_engine/print_helper_spec.rb
829
+ - pg_engine/spec/lib/pg_engine/date_jumper_spec.rb
809
830
  - pg_engine/spec/lib/pg_engine/error_helper_spec.rb
810
831
  - pg_engine/spec/lib/pg_engine/mailgun/log_sync_spec.rb
811
832
  - pg_engine/spec/lib/pg_engine/utils/pg_engine/pg_logger_spec.rb
@@ -821,7 +842,9 @@ files:
821
842
  - pg_engine/spec/pg_engine/pdf_preview_generator_spec.rb
822
843
  - pg_engine/spec/requests/admin/eventos_spec.rb
823
844
  - pg_engine/spec/requests/base_controller_requests_spec.rb
845
+ - pg_engine/spec/requests/users/date_jumper_spec.rb
824
846
  - pg_engine/spec/system/alerts_spec.rb
847
+ - pg_engine/spec/system/date_selector_spec.rb
825
848
  - pg_engine/spec/system/destroy_spec.rb
826
849
  - pg_engine/spec/system/login_spec.rb
827
850
  - pg_engine/spec/system/noticed_spec.rb
@@ -844,6 +867,7 @@ files:
844
867
  - pg_layout/app/javascript/config/turbo_rails/set_consumer.js
845
868
  - pg_layout/app/javascript/controllers/application.js
846
869
  - pg_layout/app/javascript/controllers/clear_timeout_controller.js
870
+ - pg_layout/app/javascript/controllers/date_selector_controller.js
847
871
  - pg_layout/app/javascript/controllers/fadein_onload_controller.js
848
872
  - pg_layout/app/javascript/controllers/filtros_controller.js
849
873
  - pg_layout/app/javascript/controllers/index.js
@@ -851,6 +875,8 @@ files:
851
875
  - pg_layout/app/javascript/controllers/nested_controller.js
852
876
  - pg_layout/app/javascript/controllers/notifications_controller.js
853
877
  - pg_layout/app/javascript/controllers/pg_form_controller.js
878
+ - pg_layout/app/javascript/controllers/popover_controller.js
879
+ - pg_layout/app/javascript/controllers/popover_toggler_controller.js
854
880
  - pg_layout/app/javascript/controllers/selectize_controller.js
855
881
  - pg_layout/app/javascript/controllers/switcher_controller.js
856
882
  - pg_layout/app/javascript/controllers/theme_controller.js