pg_rails 7.1.16 → 7.2.1

Sign up to get free protection for your applications and to get access to all the features.
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 -1
  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 +60 -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 +54 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc6c2d6a41256b2a5b2093e50eb1aad097f039a60a0ee32ea4e7c4efd2f01133
4
- data.tar.gz: fcd00160147fc1dbfe25e3f632433fc34e83b69018af77fc2e22c20bd23c4b2a
3
+ metadata.gz: 7685689c316550976fd129e2d10357ce1a4e3242bc5a2468d69bcbfbefe58d6c
4
+ data.tar.gz: d23282693ed8d1dbbd0552b5212bf8c7a56f9846cfcd491bedc4f4753a4f7fbd
5
5
  SHA512:
6
- metadata.gz: c4c1efe2aff72b203b3e448dfa78eeb647b00da5ccb598c13b1679a8c7cbcee4db72a9c64b0196965109c77ba8b626dea1d95d98b66856218a16a74d94734f5d
7
- data.tar.gz: 2ec78e73c57f3c1665e55b8e8885624a2ae17af16588955ad8ab135296bbbf16f2208b2776b27696c523a8ba281c9445e98a7676fa420c46ec158240b717db52
6
+ metadata.gz: a4f384000a2f7955bf91658d863bb1d52c6997cf9eeb0e775b0b4fa236af21f6eee9e5730170ba24f15a64cd8f0a2883db1aac208b5e06413a619547d73de46f
7
+ data.tar.gz: 10f9768f3f69b517839b03da38197b27e4c37adbd6cd9490cddab952ed077884548c648b7d16a4f6f1713dd2e8f59b91b91c31b1f1364df813f5b60e9c5aea24
@@ -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'
@@ -65,7 +66,6 @@ if Rails.env.local?
65
66
  require 'rubocop-rails'
66
67
  require 'rubocop-rspec'
67
68
  require 'slim_lint'
68
- require 'ruby-lint'
69
69
  require 'brakeman'
70
70
  require 'capybara'
71
71
  require 'selenium-webdriver'
@@ -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,60 @@
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
+ }
17
+
18
+ closePopover () {
19
+ const popover = this.element.closest('.popover')
20
+ this.application.getControllerForElementAndIdentifier(popover, 'popover').close()
21
+ }
22
+
23
+ async submit () {
24
+ const quantity = this.element.querySelector('input[name=quantity]').value
25
+ if (!quantity) {
26
+ this.closePopover()
27
+ return
28
+ }
29
+ const type = this.element.querySelector('select[name=type]').value
30
+ const direction = this.element.querySelector('select[name=direction]').value
31
+ const fechaEl = document.getElementById(this.element.dataset.fieldId)
32
+ const startDate = fechaEl.value
33
+ // console.log(quantity, type, direction)
34
+ this.element.querySelector('button').setAttribute('disabled', 'true')
35
+ // let input = this
36
+ const response = await get('/u/date_jumper/jump', {
37
+ query: {
38
+ start_date: startDate,
39
+ quantity,
40
+ type,
41
+ direction
42
+ },
43
+ responseKind: 'json'
44
+ })
45
+
46
+ if (response.ok) {
47
+ const json = await response.json
48
+ fechaEl.value = json.date
49
+ this.element.querySelector('button').removeAttribute('disabled')
50
+ this.closePopover()
51
+ } else {
52
+ const json = await response.json
53
+ // FIXME: handle JSON parse error
54
+ const message = json.html || 'Hubo un error'
55
+ flashMessage(message, 'warning', true)
56
+ this.element.querySelector('button').removeAttribute('disabled')
57
+ Rollbar.error('date jumper error', json)
58
+ }
59
+ }
60
+ }
@@ -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.1.16'
4
+ VERSION = '7.2.1'
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.1.16
4
+ version: 7.2.1
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
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.3.4
19
+ version: 7.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.3.4
26
+ version: 7.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: anycable
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 1.5.0
33
+ version: 1.5.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 1.5.0
40
+ version: 1.5.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: anycable-rails
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -212,14 +212,14 @@ dependencies:
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: 2.7.0
215
+ version: 2.8.1
216
216
  type: :runtime
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
- version: 2.7.0
222
+ version: 2.8.1
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: nokogiri
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -296,14 +296,14 @@ dependencies:
296
296
  requirements:
297
297
  - - "~>"
298
298
  - !ruby/object:Gem::Version
299
- version: 5.4.3
299
+ version: 5.7.0
300
300
  type: :runtime
301
301
  prerelease: false
302
302
  version_requirements: !ruby/object:Gem::Requirement
303
303
  requirements:
304
304
  - - "~>"
305
305
  - !ruby/object:Gem::Version
306
- version: 5.4.3
306
+ version: 5.7.0
307
307
  - !ruby/object:Gem::Dependency
308
308
  name: pundit
309
309
  requirement: !ruby/object:Gem::Requirement
@@ -366,14 +366,14 @@ dependencies:
366
366
  requirements:
367
367
  - - "~>"
368
368
  - !ruby/object:Gem::Version
369
- version: 3.4.2
369
+ version: '3.5'
370
370
  type: :runtime
371
371
  prerelease: false
372
372
  version_requirements: !ruby/object:Gem::Requirement
373
373
  requirements:
374
374
  - - "~>"
375
375
  - !ruby/object:Gem::Version
376
- version: 3.4.2
376
+ version: '3.5'
377
377
  - !ruby/object:Gem::Dependency
378
378
  name: jsbundling-rails
379
379
  requirement: !ruby/object:Gem::Requirement
@@ -528,6 +528,20 @@ dependencies:
528
528
  - - "~>"
529
529
  - !ruby/object:Gem::Version
530
530
  version: 2.3.6
531
+ - !ruby/object:Gem::Dependency
532
+ name: ransack
533
+ requirement: !ruby/object:Gem::Requirement
534
+ requirements:
535
+ - - "~>"
536
+ - !ruby/object:Gem::Version
537
+ version: 4.2.1
538
+ type: :runtime
539
+ prerelease: false
540
+ version_requirements: !ruby/object:Gem::Requirement
541
+ requirements:
542
+ - - "~>"
543
+ - !ruby/object:Gem::Version
544
+ version: 4.2.1
531
545
  - !ruby/object:Gem::Dependency
532
546
  name: ransack_memory
533
547
  requirement: !ruby/object:Gem::Requirement
@@ -548,14 +562,14 @@ dependencies:
548
562
  requirements:
549
563
  - - "~>"
550
564
  - !ruby/object:Gem::Version
551
- version: 3.12.1
565
+ version: '3.13'
552
566
  type: :runtime
553
567
  prerelease: false
554
568
  version_requirements: !ruby/object:Gem::Requirement
555
569
  requirements:
556
570
  - - "~>"
557
571
  - !ruby/object:Gem::Version
558
- version: 3.12.1
572
+ version: '3.13'
559
573
  - !ruby/object:Gem::Dependency
560
574
  name: noticed
561
575
  requirement: !ruby/object:Gem::Requirement
@@ -570,6 +584,20 @@ dependencies:
570
584
  - - "~>"
571
585
  - !ruby/object:Gem::Version
572
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'
573
601
  description: Rails goodies.
574
602
  email:
575
603
  - mrosso10@gmail.com
@@ -611,7 +639,10 @@ files:
611
639
  - pg_engine/app/components/alert_component.html.slim
612
640
  - pg_engine/app/components/alert_component.rb
613
641
  - pg_engine/app/components/bad_request_component.rb
642
+ - pg_engine/app/components/bad_user_input_component.rb
614
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
615
646
  - pg_engine/app/components/flash_container_component.rb
616
647
  - pg_engine/app/components/internal_error_component.rb
617
648
  - pg_engine/app/components/notification_component.rb
@@ -635,6 +666,7 @@ files:
635
666
  - pg_engine/app/controllers/public/mensaje_contactos_controller.rb
636
667
  - pg_engine/app/controllers/public/webhooks_controller.rb
637
668
  - pg_engine/app/controllers/users/confirmations_controller.rb
669
+ - pg_engine/app/controllers/users/date_jumper_controller.rb
638
670
  - pg_engine/app/controllers/users/notifications_controller.rb
639
671
  - pg_engine/app/controllers/users/registrations_controller.rb
640
672
  - pg_engine/app/decorators/account_decorator.rb
@@ -654,6 +686,7 @@ files:
654
686
  - pg_engine/app/helpers/pg_engine/print_helper.rb
655
687
  - pg_engine/app/helpers/pg_engine/route_helper.rb
656
688
  - pg_engine/app/inputs/pg_engine/fecha_input.rb
689
+ - pg_engine/app/lib/pg_engine/date_jumper.rb
657
690
  - pg_engine/app/lib/pg_engine/devise_failure_app.rb
658
691
  - pg_engine/app/lib/pg_engine/error_helper.rb
659
692
  - pg_engine/app/lib/pg_engine/filtros_builder.rb
@@ -767,6 +800,7 @@ files:
767
800
  - pg_engine/spec/components/previews/alert_component_preview/colours.html.slim
768
801
  - pg_engine/spec/components/previews/alert_component_preview/default.html.slim
769
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
770
804
  - pg_engine/spec/components/previews/alert_component_preview/tooltips.html.slim
771
805
  - pg_engine/spec/components/previews/internal_error_preview.rb
772
806
  - pg_engine/spec/components/previews/internal_error_preview/default.html.slim
@@ -792,6 +826,7 @@ files:
792
826
  - pg_engine/spec/fixtures/test.pdf
793
827
  - pg_engine/spec/helpers/pg_engine/pg_rails_helper_spec.rb
794
828
  - pg_engine/spec/helpers/pg_engine/print_helper_spec.rb
829
+ - pg_engine/spec/lib/pg_engine/date_jumper_spec.rb
795
830
  - pg_engine/spec/lib/pg_engine/error_helper_spec.rb
796
831
  - pg_engine/spec/lib/pg_engine/mailgun/log_sync_spec.rb
797
832
  - pg_engine/spec/lib/pg_engine/utils/pg_engine/pg_logger_spec.rb
@@ -807,7 +842,9 @@ files:
807
842
  - pg_engine/spec/pg_engine/pdf_preview_generator_spec.rb
808
843
  - pg_engine/spec/requests/admin/eventos_spec.rb
809
844
  - pg_engine/spec/requests/base_controller_requests_spec.rb
845
+ - pg_engine/spec/requests/users/date_jumper_spec.rb
810
846
  - pg_engine/spec/system/alerts_spec.rb
847
+ - pg_engine/spec/system/date_selector_spec.rb
811
848
  - pg_engine/spec/system/destroy_spec.rb
812
849
  - pg_engine/spec/system/login_spec.rb
813
850
  - pg_engine/spec/system/noticed_spec.rb
@@ -830,6 +867,7 @@ files:
830
867
  - pg_layout/app/javascript/config/turbo_rails/set_consumer.js
831
868
  - pg_layout/app/javascript/controllers/application.js
832
869
  - pg_layout/app/javascript/controllers/clear_timeout_controller.js
870
+ - pg_layout/app/javascript/controllers/date_selector_controller.js
833
871
  - pg_layout/app/javascript/controllers/fadein_onload_controller.js
834
872
  - pg_layout/app/javascript/controllers/filtros_controller.js
835
873
  - pg_layout/app/javascript/controllers/index.js
@@ -837,6 +875,8 @@ files:
837
875
  - pg_layout/app/javascript/controllers/nested_controller.js
838
876
  - pg_layout/app/javascript/controllers/notifications_controller.js
839
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
840
880
  - pg_layout/app/javascript/controllers/selectize_controller.js
841
881
  - pg_layout/app/javascript/controllers/switcher_controller.js
842
882
  - pg_layout/app/javascript/controllers/theme_controller.js