pg_rails 7.0.1
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +73 -0
- data/Rakefile +36 -0
- data/app/assets/javascripts/pg_rails/asociacion_creable.js +85 -0
- data/app/assets/javascripts/pg_rails/best_in_place_datepicker.js +58 -0
- data/app/assets/javascripts/pg_rails/librerias.js +13 -0
- data/app/assets/javascripts/pg_rails/librerias_b3.js +14 -0
- data/app/assets/javascripts/pg_rails/validaciones.js +44 -0
- data/app/assets/javascripts/pg_rails.js +318 -0
- data/app/assets/stylesheets/pg_rails/librerias.scss +5 -0
- data/app/assets/stylesheets/pg_rails/pg_chosen.scss +29 -0
- data/app/assets/stylesheets/pg_rails/pg_rails.scss +199 -0
- data/app/assets/stylesheets/pg_rails_b3.scss +10 -0
- data/app/assets/stylesheets/pg_rails_b4.scss +12 -0
- data/app/assets/stylesheets/pg_rails_b5.scss +1 -0
- data/app/controllers/pg_rails/application_controller.rb +316 -0
- data/app/controllers/pg_rails/editar_en_lugar_controller.rb +24 -0
- data/app/decorators/pg_rails/base_decorator.rb +120 -0
- data/app/helpers/pg_rails/editar_en_lugar_helper.rb +106 -0
- data/app/helpers/pg_rails/form_helper.rb +25 -0
- data/app/helpers/pg_rails/postgres_helper.rb +15 -0
- data/app/helpers/pg_rails/print_helper.rb +176 -0
- data/app/inputs/pg_rails/asociacion_creable_input.rb +72 -0
- data/app/inputs/pg_rails/fecha_input.rb +20 -0
- data/app/inputs/pg_rails/selects_dependientes_input.rb +9 -0
- data/app/lib/pg_form_builder.rb +31 -0
- data/app/lib/pg_rails/filtros_builder.rb +338 -0
- data/app/models/pg_rails/application_record.rb +51 -0
- data/app/policies/pg_rails/application_policy.rb +104 -0
- data/app/views/application/_abrir_modal.js.erb +14 -0
- data/app/views/application/_actualizar_smart_listing.html.slim +3 -0
- data/app/views/application/_cerrar_modal.js.erb +8 -0
- data/app/views/application/_modal_ajax_form.js.erb +7 -0
- data/config/brakeman.ignore +42 -0
- data/config/locales/es.yml +17 -0
- data/config/routes.rb +3 -0
- data/config/spring.rb +1 -0
- data/lib/pg_rails/configuracion.rb +24 -0
- data/lib/pg_rails/core_ext.rb +17 -0
- data/lib/pg_rails/engine.rb +42 -0
- data/lib/pg_rails/simple_form/initializer.rb +583 -0
- data/lib/pg_rails/utils/logueador.rb +39 -0
- data/lib/pg_rails/version.rb +5 -0
- data/lib/pg_rails.rb +23 -0
- data/lib/tasks/auto_anotar_modelos.rake +34 -0
- data/lib/tasks/pg_rails_tasks.rake +5 -0
- metadata +89 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
module EditarEnLugarHelper
|
5
|
+
def editar_en_lugar(objeto, atributo, tipo = :input, url = nil, collection = nil)
|
6
|
+
url = pg_rails.editar_en_lugar_path(objeto) if url.nil?
|
7
|
+
if tipo == :checkbox
|
8
|
+
best_in_place objeto, atributo, url: url, as: tipo, collection: %w[No Si],
|
9
|
+
param: objeto.model_name.name
|
10
|
+
elsif tipo == :date
|
11
|
+
best_in_place objeto, atributo, url: url, as: tipo, display_with: lambda { |v|
|
12
|
+
dmy(v)
|
13
|
+
}, param: objeto.model_name.name
|
14
|
+
# best_in_place objeto, atributo, url: editar_en_lugarurl(objeto), as: tipo, display_with: lambda { |v| dmy(v) }, class: 'datefield'
|
15
|
+
elsif tipo == :textarea
|
16
|
+
funcion = lambda do |valor|
|
17
|
+
return unless valor.present?
|
18
|
+
|
19
|
+
valor.gsub!("\r\n", '<br>')
|
20
|
+
valor.gsub!("\n", '<br>')
|
21
|
+
valor.html_safe
|
22
|
+
end
|
23
|
+
best_in_place objeto, atributo, url: url, as: tipo, display_with: funcion,
|
24
|
+
param: objeto.model_name.name
|
25
|
+
elsif tipo == :select && collection.present?
|
26
|
+
best_in_place objeto, atributo, url: url, as: tipo, collection: collection,
|
27
|
+
param: objeto.model_name.name, value: objeto.send(atributo), inner_class: 'form-control'
|
28
|
+
else
|
29
|
+
best_in_place objeto, atributo, url: url, as: tipo, param: objeto.model_name.name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Versión mejorada de editar_en_lugar, pero le pongo v2 por retrocompatibilidad
|
34
|
+
# La diferencia es que recibe un hash "options" y se le pueden agregar cualquiera de las options
|
35
|
+
# que admite best_in_place
|
36
|
+
def editar_en_lugar_v2(objeto, atributo, tipo = :input, options = {})
|
37
|
+
options[:url] = pg_rails.editar_en_lugar_path(objeto) if options[:url].nil?
|
38
|
+
options[:as] = tipo
|
39
|
+
options[:param] = objeto.model_name.name
|
40
|
+
options[:inner_class] = 'form-control' if options[:inner_class].nil?
|
41
|
+
options[:class] = 'editar_en_lugar_v2'
|
42
|
+
options[:html_attrs] = { autocomplete: :off }
|
43
|
+
# url = pg_rails.editar_en_lugar_path(objeto) if url.nil?
|
44
|
+
if tipo == :checkbox
|
45
|
+
options[:collection] = %w[No Si]
|
46
|
+
|
47
|
+
elsif tipo == :date
|
48
|
+
options[:display_with] = ->(v) { dmy(v) } if options[:display_with].nil?
|
49
|
+
|
50
|
+
elsif tipo == :textarea
|
51
|
+
funcion = lambda do |valor|
|
52
|
+
return unless valor.present?
|
53
|
+
|
54
|
+
valor.gsub!("\r\n", '<br>')
|
55
|
+
valor.gsub!("\n", '<br>')
|
56
|
+
valor.html_safe
|
57
|
+
end
|
58
|
+
options[:display_with] = funcion if options[:display_with].nil?
|
59
|
+
|
60
|
+
elsif tipo == :select && options[:collection].present?
|
61
|
+
options[:value] = objeto.send(atributo)
|
62
|
+
end
|
63
|
+
|
64
|
+
best_in_place objeto, atributo, options
|
65
|
+
end
|
66
|
+
|
67
|
+
# TODO: mover a otro helper
|
68
|
+
def encabezado(campo, options = {})
|
69
|
+
clase = (options[:clase] || @clase_modelo)
|
70
|
+
if options[:ordenable]
|
71
|
+
field = controller.instance_variable_get(:"@field")
|
72
|
+
direction = controller.instance_variable_get(:"@direction")
|
73
|
+
uri = URI.parse(request.url)
|
74
|
+
if uri.query.present?
|
75
|
+
cgi = CGI.parse(uri.query)
|
76
|
+
else
|
77
|
+
cgi = {}
|
78
|
+
end
|
79
|
+
cgi["order_by"] = campo
|
80
|
+
cgi["order_direction"] =
|
81
|
+
if field.to_s == campo.to_s && direction.to_s == 'asc'
|
82
|
+
'desc'
|
83
|
+
else
|
84
|
+
'asc'
|
85
|
+
end
|
86
|
+
|
87
|
+
if field.to_s == campo.to_s
|
88
|
+
symbol =
|
89
|
+
if direction.to_s == 'asc'
|
90
|
+
'<i class="bi bi-sort-down-alt" />'
|
91
|
+
elsif direction.to_s == 'desc'
|
92
|
+
'<i class="bi bi-sort-up" />'
|
93
|
+
end
|
94
|
+
else
|
95
|
+
symbol = ''
|
96
|
+
end
|
97
|
+
|
98
|
+
uri.query = cgi.map {|a,b| [a, (b.length == 1 ? b.first : b)]}.to_h.to_query
|
99
|
+
|
100
|
+
link_to(clase.human_attribute_name(campo), uri.to_s) + " #{symbol}".html_safe
|
101
|
+
else
|
102
|
+
clase.human_attribute_name(campo)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
module FormHelper
|
5
|
+
def pg_form_for(object, *args, &block)
|
6
|
+
options = args.extract_options!
|
7
|
+
|
8
|
+
options[:builder] = PgFormBuilder
|
9
|
+
options[:html] ||= {}
|
10
|
+
options[:html][:class] = if options[:html].key?(:class)
|
11
|
+
['pg-form', options[:html][:class]].compact
|
12
|
+
else
|
13
|
+
'pg-form'
|
14
|
+
end
|
15
|
+
|
16
|
+
simple_form_for(object, *(args << options), &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def url_change_format(url)
|
20
|
+
uri = URI.parse(url)
|
21
|
+
uri.path = "#{uri.path}.xlsx"
|
22
|
+
uri.to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
module PostgresHelper
|
5
|
+
# Le pone la timezone
|
6
|
+
def add_timezone(field)
|
7
|
+
"#{field}::TIMESTAMPTZ AT TIME ZONE INTERVAL '-03:00'::INTERVAL"
|
8
|
+
end
|
9
|
+
|
10
|
+
# Le pone la timezone y lo convierte a Date
|
11
|
+
def get_date_tz(field)
|
12
|
+
"(#{add_timezone(field)})::date"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
module PrintHelper
|
5
|
+
include ActionView::Helpers::NumberHelper
|
6
|
+
|
7
|
+
class FechaInvalidaError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Genera un falso link que al clickear carga la url por ajax
|
11
|
+
# Es igual a los links con remote: true, pero evita que abran el link en otra
|
12
|
+
# pestaña. Movido de probella
|
13
|
+
def pg_ajax_link(url, options = {})
|
14
|
+
content_tag :span, class: 'pg_ajax_link', data: options.merge(url: url) do
|
15
|
+
block_given? ? yield : ''
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def mostrar_con_link(objeto, options = {})
|
20
|
+
return unless objeto.present?
|
21
|
+
|
22
|
+
if policy(objeto).show?
|
23
|
+
content = truncate_title(block_given? ? yield : objeto)
|
24
|
+
if options[:new_tab]
|
25
|
+
content += " <i class='fa fa-external-link'>".html_safe
|
26
|
+
link_to content.html_safe, objeto, target: :_blank
|
27
|
+
else
|
28
|
+
link_to content.html_safe, objeto
|
29
|
+
end
|
30
|
+
else
|
31
|
+
truncate_title(block_given? ? yield : objeto)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def truncate_title(input, length = 20)
|
36
|
+
string = input.to_s
|
37
|
+
if string.length > length
|
38
|
+
content_tag :span, title: input, rel: :tooltip do
|
39
|
+
truncate string, length: length
|
40
|
+
end
|
41
|
+
else
|
42
|
+
string
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def print_cuit(cuit_number)
|
47
|
+
return '' unless cuit_number.present?
|
48
|
+
|
49
|
+
str = cuit_number.to_s
|
50
|
+
"#{str[0..1]}-#{str[2..9]}-#{str[10]}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def dmy_time(date)
|
54
|
+
date = parsear_tiempo(date) if date.is_a? String
|
55
|
+
return unless date.present?
|
56
|
+
|
57
|
+
date.strftime('%d/%m/%Y %H:%M')
|
58
|
+
end
|
59
|
+
|
60
|
+
def dmy(date)
|
61
|
+
date = parsear_fecha(date) if date.is_a? String
|
62
|
+
return unless date.present?
|
63
|
+
|
64
|
+
date.strftime('%d/%m/%Y')
|
65
|
+
end
|
66
|
+
|
67
|
+
def ymd(date)
|
68
|
+
date = parsear_fecha(date) if date.is_a? String
|
69
|
+
return unless date.present?
|
70
|
+
|
71
|
+
date.strftime('%Y/%m/%d')
|
72
|
+
end
|
73
|
+
|
74
|
+
def dmyg(date)
|
75
|
+
date = parsear_fecha(date) if date.is_a? String
|
76
|
+
return unless date.present?
|
77
|
+
|
78
|
+
date.strftime('%d-%m-%Y')
|
79
|
+
end
|
80
|
+
|
81
|
+
def ymdg(date)
|
82
|
+
date = parsear_fecha(date) if date.is_a? String
|
83
|
+
return unless date.present?
|
84
|
+
|
85
|
+
date.strftime('%Y-%m-%d')
|
86
|
+
end
|
87
|
+
|
88
|
+
def myg(date)
|
89
|
+
date = parsear_fecha(date) if date.is_a? String
|
90
|
+
return unless date.present?
|
91
|
+
|
92
|
+
date.strftime('%m-%Y')
|
93
|
+
end
|
94
|
+
|
95
|
+
def print_number(number)
|
96
|
+
number_with_precision(number, delimiter: ',', separator: '.', precision: 2)
|
97
|
+
end
|
98
|
+
|
99
|
+
def print_number_coma(number)
|
100
|
+
number_with_precision(number, delimiter: '.', separator: ',', precision: 2)
|
101
|
+
end
|
102
|
+
|
103
|
+
def print_boolean(boolean)
|
104
|
+
return if boolean.nil?
|
105
|
+
return 'Si' if boolean
|
106
|
+
|
107
|
+
'No'
|
108
|
+
end
|
109
|
+
|
110
|
+
def print_currency(number, moneda = 'pesos')
|
111
|
+
return unless number.present?
|
112
|
+
|
113
|
+
"<span class='currency #{moneda}'>#{number_with_precision(number, delimiter: '.',
|
114
|
+
separator: ',', precision: 2)}</span>".html_safe
|
115
|
+
end
|
116
|
+
|
117
|
+
def print_currency2(number, moneda = 'pesos')
|
118
|
+
return unless number.present?
|
119
|
+
|
120
|
+
"#{simbolo_moneda(moneda)} #{number_with_precision(number, delimiter: '.', separator: ',',
|
121
|
+
precision: 2)}"
|
122
|
+
end
|
123
|
+
|
124
|
+
def simbolo_moneda(moneda)
|
125
|
+
return '$' if moneda == 'pesos'
|
126
|
+
return 'U$S' if moneda == 'dolares'
|
127
|
+
return '€' if moneda == 'euros'
|
128
|
+
return 'R$' if moneda == 'reales'
|
129
|
+
return 'CLP' if moneda == 'pesos_chilenos'
|
130
|
+
return 'MXN' if moneda == 'pesos_mexicanos'
|
131
|
+
|
132
|
+
'$'
|
133
|
+
end
|
134
|
+
|
135
|
+
def print_value(nombre_clase, field, value)
|
136
|
+
if !value.nil? == value # es booleano
|
137
|
+
value ? 'Si' : 'No'
|
138
|
+
elsif value.nil?
|
139
|
+
'-'
|
140
|
+
else
|
141
|
+
begin
|
142
|
+
if nombre_clase.constantize.defined_enums[field].present?
|
143
|
+
valor = nombre_clase.constantize.defined_enums[field].invert[value]
|
144
|
+
I18n.t("enums.#{nombre_clase.downcase}.#{field}.#{valor}", default: valor)
|
145
|
+
else
|
146
|
+
truncate_title(value.to_s.encode('UTF-8', invalid: :replace, undef: :replace))
|
147
|
+
end
|
148
|
+
rescue NameError
|
149
|
+
truncate_title(value.to_s.encode('UTF-8', invalid: :replace, undef: :replace))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def parsear_tiempo(datetime)
|
155
|
+
return nil unless datetime.present?
|
156
|
+
|
157
|
+
DateTime.parse(datetime)
|
158
|
+
rescue ArgumentError
|
159
|
+
raise FechaInvalidaError, datetime
|
160
|
+
end
|
161
|
+
|
162
|
+
def parsear_fecha(date)
|
163
|
+
return nil unless date.present?
|
164
|
+
|
165
|
+
Date.parse(date)
|
166
|
+
rescue ArgumentError
|
167
|
+
raise FechaInvalidaError, date
|
168
|
+
end
|
169
|
+
|
170
|
+
def show_percentage(value)
|
171
|
+
return unless value.present?
|
172
|
+
|
173
|
+
"#{value.round(2)} %"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
class AsociacionCreableInput < SimpleForm::Inputs::StringInput
|
5
|
+
include ActionView::Helpers::FormTagHelper
|
6
|
+
|
7
|
+
def boton(wrapper_options = {})
|
8
|
+
if PgRails.config.bootstrap_version >= 4
|
9
|
+
button_tag('', wrapper_options)
|
10
|
+
else
|
11
|
+
button_tag('<span class="caret">'.html_safe, wrapper_options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def hidden_input(wrapper_options = {})
|
16
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
17
|
+
merged_input_options = merge_wrapper_options(merged_input_options, { class: 'oculto' })
|
18
|
+
@builder.text_field(attribute_name, merged_input_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def input(wrapper_options = nil)
|
22
|
+
unless string?
|
23
|
+
input_html_classes.unshift('string')
|
24
|
+
input_html_options[:type] ||= input_type if html5?
|
25
|
+
end
|
26
|
+
|
27
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
28
|
+
merged_input_options = merge_wrapper_options(merged_input_options, { class: 'keep-disabled' })
|
29
|
+
|
30
|
+
text_field_tag(nil, object.send(reflection.name).to_s, merged_input_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def seleccionar_asociado(wrapper_options = {})
|
34
|
+
icon = content_tag :span, nil, class: 'fa fa-hand-pointer'
|
35
|
+
merged_input_options = merge_wrapper_options(wrapper_options,
|
36
|
+
{ class: 'seleccionar_asociado dropdown-item', href: 'javascript:void(0)',
|
37
|
+
data: { url: options[:url_seleccionar] } })
|
38
|
+
anchor = content_tag :a, "#{icon} Seleccionar".html_safe, merged_input_options
|
39
|
+
if PgRails.config.bootstrap_version >= 4
|
40
|
+
anchor
|
41
|
+
else
|
42
|
+
"<li>#{anchor}</li>".html_safe
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def crear_asociado(wrapper_options = {})
|
47
|
+
icon = content_tag :span, nil, class: 'fa fa-plus-square'
|
48
|
+
merged_input_options = merge_wrapper_options(wrapper_options,
|
49
|
+
{ class: 'crear_asociado dropdown-item', href: 'javascript:void(0)',
|
50
|
+
data: { url: options[:url_crear] } })
|
51
|
+
anchor = content_tag :a, "#{icon} Crear".html_safe, merged_input_options
|
52
|
+
if PgRails.config.bootstrap_version >= 4
|
53
|
+
anchor
|
54
|
+
else
|
55
|
+
"<li>#{anchor}</li>".html_safe
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def borrar_seleccion(wrapper_options = {})
|
60
|
+
icon = content_tag :span, nil, class: 'fa fa-trash'
|
61
|
+
merged_input_options = merge_wrapper_options(wrapper_options,
|
62
|
+
{ class: 'borrar_seleccion dropdown-item',
|
63
|
+
href: 'javascript:void(0)' })
|
64
|
+
anchor = content_tag :a, "#{icon} Borrar selección".html_safe, merged_input_options
|
65
|
+
if PgRails.config.bootstrap_version >= 4
|
66
|
+
anchor
|
67
|
+
else
|
68
|
+
"<li>#{anchor}</li>".html_safe
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
class FechaInput < SimpleForm::Inputs::StringInput
|
5
|
+
def input(wrapper_options = nil)
|
6
|
+
# esto es porque si no Rails llama a value_before_type_cast
|
7
|
+
if object.is_a? Draper::Decorator
|
8
|
+
# Salteo el decorator para que me tome la fecha con formato inglés
|
9
|
+
value = object.object.public_send(attribute_name)
|
10
|
+
else
|
11
|
+
value = object.public_send(attribute_name)
|
12
|
+
end
|
13
|
+
@input_type = 'date'
|
14
|
+
|
15
|
+
options = merge_wrapper_options({ value: value, class: '', autocomplete: 'off' },
|
16
|
+
wrapper_options)
|
17
|
+
super(options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# TODO: fix hackeo
|
4
|
+
# class PgFormBuilder < NestedForm::SimpleBuilder
|
5
|
+
class PgFormBuilder < SimpleForm::FormBuilder
|
6
|
+
def mensajes_de_error
|
7
|
+
return unless object.errors.present?
|
8
|
+
|
9
|
+
errors = object.errors.full_messages.map { |m| "<li>#{m}</li>" }.join
|
10
|
+
"<div class='alert alert-danger'>#{errors}</div>".html_safe
|
11
|
+
end
|
12
|
+
|
13
|
+
map_type :date, to: PgRails::FechaInput
|
14
|
+
# map_type :datetime, to: PgRails::FechaInput
|
15
|
+
|
16
|
+
def asociacion_creable(atributo, url_seleccionar, url_crear, options = {})
|
17
|
+
options[:as] = 'pg_rails/asociacion_creable'
|
18
|
+
options[:wrapper] = :asociacion_creable
|
19
|
+
options[:url_seleccionar] = url_seleccionar
|
20
|
+
options[:url_crear] = url_crear
|
21
|
+
options[:wrapper_html] = { class: 'completado' } if object.send(atributo).present?
|
22
|
+
association atributo, options
|
23
|
+
end
|
24
|
+
|
25
|
+
def submit_button(*args, &block)
|
26
|
+
options = args.extract_options!.dup
|
27
|
+
options[:class] = ['btn-primary', options[:class]].compact
|
28
|
+
args << options
|
29
|
+
send(:submit, *args, &block)
|
30
|
+
end
|
31
|
+
end
|