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,29 @@
|
|
1
|
+
|
2
|
+
body .chosen-container-active.chosen-with-drop .chosen-single {
|
3
|
+
background: none;
|
4
|
+
}
|
5
|
+
body .chosen-container-single .chosen-single {
|
6
|
+
padding-top: 2px;
|
7
|
+
border: 1px solid #e5e6e7;
|
8
|
+
border: 1px solid #ced4da;
|
9
|
+
background: none;
|
10
|
+
box-shadow: none;
|
11
|
+
}
|
12
|
+
|
13
|
+
.chosen-container.chosen-with-drop .chosen-drop {
|
14
|
+
// margin-top: 0px;
|
15
|
+
}
|
16
|
+
.chosen-container-single a.chosen-single {
|
17
|
+
height: 36px;
|
18
|
+
line-height: 30px;
|
19
|
+
}
|
20
|
+
.chosen-container-single .chosen-single div {
|
21
|
+
padding-top: 5px;
|
22
|
+
}
|
23
|
+
.chosen-container-single .chosen-drop {
|
24
|
+
min-width: 190px;
|
25
|
+
margin-top: -3px;
|
26
|
+
}
|
27
|
+
.chosen-container.chosen-container-single .chosen-single {
|
28
|
+
border-radius: 4px;
|
29
|
+
}
|
@@ -0,0 +1,199 @@
|
|
1
|
+
// @import 'pg_rails/pg_chosen';
|
2
|
+
|
3
|
+
// Google Maps Places API
|
4
|
+
// Para que funcione en los modales
|
5
|
+
.pac-container {
|
6
|
+
z-index: 1051 !important;
|
7
|
+
}
|
8
|
+
|
9
|
+
.simple_form {
|
10
|
+
.ocultar {
|
11
|
+
input, select, textarea {
|
12
|
+
display: none;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
.form-group.asociacion_creable {
|
17
|
+
input.oculto {
|
18
|
+
visibility: hidden;
|
19
|
+
position: absolute;
|
20
|
+
}
|
21
|
+
|
22
|
+
&:not(.completado) {
|
23
|
+
.borrar_seleccion {
|
24
|
+
display: none;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
// oculto la columna de actions
|
29
|
+
.modal-seleccionar-asociado .listado th:last-child,
|
30
|
+
.modal-seleccionar-asociado .listado td:last-child {
|
31
|
+
display: none;
|
32
|
+
}
|
33
|
+
.modal-seleccionar-asociado .listado {
|
34
|
+
td {
|
35
|
+
cursor: pointer;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
.modal-seleccionar-asociado .listado tr:hover {
|
39
|
+
background-color: lightgrey;
|
40
|
+
}
|
41
|
+
|
42
|
+
.listado {
|
43
|
+
td, th {
|
44
|
+
padding: 0.25rem 1rem;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
.listado .btn-xs {
|
48
|
+
margin-right: 4px;
|
49
|
+
}
|
50
|
+
.listado .btn-sm {
|
51
|
+
min-width: 25px;
|
52
|
+
height: 25px;
|
53
|
+
padding: 1px;
|
54
|
+
margin-right: 4px;
|
55
|
+
}
|
56
|
+
|
57
|
+
.form-group.producto {
|
58
|
+
.form-control.selectize-control {
|
59
|
+
height: 36px;
|
60
|
+
// width: 200px;
|
61
|
+
}
|
62
|
+
.chosen-container {
|
63
|
+
// max-width: 200px;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
// hay que agregar la clase pg-form a los forms que queremos afectar
|
67
|
+
.pg-form {
|
68
|
+
max-width: 1000px;
|
69
|
+
|
70
|
+
.form-control {
|
71
|
+
font-size: 13px;
|
72
|
+
}
|
73
|
+
|
74
|
+
.form-control.selectize-control {
|
75
|
+
height: 36px;
|
76
|
+
}
|
77
|
+
.form-group {
|
78
|
+
/*transition: height .5s ease 0s;*/
|
79
|
+
transition: opacity .3s ease 0s;
|
80
|
+
opacity: 1;
|
81
|
+
max-width: 300px;
|
82
|
+
margin-bottom: 6px;
|
83
|
+
|
84
|
+
&.datetime {
|
85
|
+
max-width: 600px;
|
86
|
+
}
|
87
|
+
|
88
|
+
&.dependent_fields {
|
89
|
+
max-width: 600px;
|
90
|
+
}
|
91
|
+
|
92
|
+
&.ocultar {
|
93
|
+
/*height: 0px;*/
|
94
|
+
opacity: 0;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
.form-control.error {
|
99
|
+
border: 1px solid red;
|
100
|
+
}
|
101
|
+
|
102
|
+
label.error {
|
103
|
+
color: red;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
.filter {
|
108
|
+
display: inline-block;
|
109
|
+
// margin-right: 10px;
|
110
|
+
// margin-bottom: 10px;
|
111
|
+
vertical-align: top;
|
112
|
+
min-width: 200px;
|
113
|
+
|
114
|
+
.input-group {
|
115
|
+
width: 230px;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
.dependent_fields select {
|
120
|
+
// width: calc(99% / 2);
|
121
|
+
// width: 500px;
|
122
|
+
display: block;
|
123
|
+
margin-bottom: 15px;
|
124
|
+
}
|
125
|
+
|
126
|
+
.dependent_fields label {
|
127
|
+
display: block;
|
128
|
+
text-align: left!important;
|
129
|
+
}
|
130
|
+
|
131
|
+
.dependent_fields {
|
132
|
+
// max-width: 400px;
|
133
|
+
}
|
134
|
+
|
135
|
+
.btn.exportar:hover {
|
136
|
+
cursor: pointer;
|
137
|
+
}
|
138
|
+
|
139
|
+
|
140
|
+
// Editar en lugar
|
141
|
+
.editar_en_lugar_v2 {
|
142
|
+
cursor: pointer;
|
143
|
+
text-decoration: underline dotted lightgrey;
|
144
|
+
}
|
145
|
+
.editar_en_lugar_v2::after {
|
146
|
+
padding-left: 13px;
|
147
|
+
content: '✎';
|
148
|
+
opacity: 0;
|
149
|
+
}
|
150
|
+
.editar_en_lugar_v2:hover::after {
|
151
|
+
opacity: 1;
|
152
|
+
}
|
153
|
+
|
154
|
+
.editar_en_lugar_v2 form {
|
155
|
+
display: inline-block!important;
|
156
|
+
}
|
157
|
+
.editar_en_lugar_v2 input {
|
158
|
+
display: inline-block;
|
159
|
+
}
|
160
|
+
.editar_en_lugar_v2 input[type=submit] {
|
161
|
+
margin-left: 10px;
|
162
|
+
}
|
163
|
+
|
164
|
+
.pg_ajax_link {
|
165
|
+
cursor: pointer;
|
166
|
+
color: #337ab7;
|
167
|
+
text-decoration: none;
|
168
|
+
}
|
169
|
+
.pg_ajax_link:hover {
|
170
|
+
color: #23527c;
|
171
|
+
text-decoration: underline;
|
172
|
+
}
|
173
|
+
|
174
|
+
.pg-max-width-xxs {
|
175
|
+
max-width: 350px;
|
176
|
+
}
|
177
|
+
.pg-max-width-xs {
|
178
|
+
max-width: 450px;
|
179
|
+
}
|
180
|
+
.pg-max-width-sm {
|
181
|
+
max-width: 600px;
|
182
|
+
}
|
183
|
+
.pg-max-width {
|
184
|
+
max-width: 800px;
|
185
|
+
}
|
186
|
+
.pg-max-width-lg {
|
187
|
+
max-width: 1000px;
|
188
|
+
}
|
189
|
+
.pg-max-width-xl {
|
190
|
+
max-width: 1200px;
|
191
|
+
}
|
192
|
+
|
193
|
+
.pg-revert-width {
|
194
|
+
width: revert;
|
195
|
+
}
|
196
|
+
|
197
|
+
.pg-form input.date {
|
198
|
+
max-width: 140px;
|
199
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
@import 'pg_rails/pg_rails';
|
@@ -0,0 +1,316 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
class ApplicationController < ActionController::Base
|
5
|
+
include ApplicationHelper
|
6
|
+
include Pundit::Authorization
|
7
|
+
# include SmartListing::Helper::ControllerExtensions
|
8
|
+
# helper SmartListing::Helper
|
9
|
+
include PrintHelper
|
10
|
+
include PostgresHelper
|
11
|
+
|
12
|
+
rescue_from PrintHelper::FechaInvalidaError, with: :fecha_invalida
|
13
|
+
rescue_from Pundit::NotAuthorizedError, with: :not_authorized
|
14
|
+
|
15
|
+
layout :setear_layout
|
16
|
+
|
17
|
+
def self.inherited(klass)
|
18
|
+
super
|
19
|
+
# incluyo los helpers de /app/helpers de la main_app
|
20
|
+
klass.helper :all
|
21
|
+
end
|
22
|
+
|
23
|
+
helper_method :mobile_device?
|
24
|
+
|
25
|
+
def mobile_device?
|
26
|
+
request.user_agent =~ /Mobile|webOS/
|
27
|
+
end
|
28
|
+
|
29
|
+
helper_method :any_filter?
|
30
|
+
|
31
|
+
def any_filter?
|
32
|
+
params.keys.reject { |a| a.in? ["controller", "action", "page", "page_size", "order_by", "order_direction"] }.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
helper_method :current_page_size
|
37
|
+
|
38
|
+
def current_page_size
|
39
|
+
if params[:page_size].present?
|
40
|
+
session[:page_size] = params[:page_size]
|
41
|
+
params[:page_size].to_i
|
42
|
+
else
|
43
|
+
default_page_size
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_page_size
|
48
|
+
session[:page_size].present? ? session[:page_size].to_i : 10
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def pg_respond_update(object: nil, extra_js: nil)
|
55
|
+
object ||= instancia_modelo
|
56
|
+
respond_to do |format|
|
57
|
+
if (@saved = object.save)
|
58
|
+
format.html do
|
59
|
+
redirect_to object.decorate.target_object
|
60
|
+
end
|
61
|
+
format.json { render json: object.decorate }
|
62
|
+
else
|
63
|
+
format.turbo_stream do
|
64
|
+
flash.now[:error] = object.errors.full_messages.join(', ')
|
65
|
+
render turbo_stream: render_turbo_stream_flash_messages
|
66
|
+
end
|
67
|
+
format.html { render :edit, status: :unprocessable_entity }
|
68
|
+
format.json { render json: object.errors, status: :unprocessable_entity }
|
69
|
+
end
|
70
|
+
format.js do
|
71
|
+
render '_cerrar_modal', locals: {
|
72
|
+
contenido: 'form', extra_js: ['modal_ajax_form', extra_js]
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def pg_respond_create(object: nil, extra_js: nil)
|
79
|
+
object ||= instancia_modelo
|
80
|
+
respond_to do |format|
|
81
|
+
if (@saved = object.save)
|
82
|
+
format.html do
|
83
|
+
if params[:save_and_next] == 'true'
|
84
|
+
new_path = url_for(@clase_modelo) + "/new"
|
85
|
+
redirect_to new_path, notice: "#{@clase_modelo.nombre_singular} creado."
|
86
|
+
else
|
87
|
+
redirect_to object.decorate.target_object
|
88
|
+
end
|
89
|
+
end
|
90
|
+
format.json { render json: object.decorate }
|
91
|
+
else
|
92
|
+
format.turbo_stream do
|
93
|
+
flash.now[:error] = object.errors.full_messages.join(', ')
|
94
|
+
render turbo_stream: render_turbo_stream_flash_messages
|
95
|
+
end
|
96
|
+
format.html { render :new, status: :unprocessable_entity }
|
97
|
+
format.json { render json: object.errors.full_messages, status: :unprocessable_entity }
|
98
|
+
end
|
99
|
+
format.js do
|
100
|
+
render '_cerrar_modal', locals: {
|
101
|
+
contenido: 'form', extra_js: ['modal_ajax_form', extra_js]
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def pg_respond_index(collection)
|
108
|
+
respond_to do |format|
|
109
|
+
format.json { render json: collection }
|
110
|
+
format.js { render_smart_listing }
|
111
|
+
format.html { render_smart_listing }
|
112
|
+
format.xlsx do
|
113
|
+
render xlsx: 'download',
|
114
|
+
filename: "#{@clase_modelo.nombre_plural.gsub(' ', '-').downcase}" \
|
115
|
+
"-#{Time.zone.now.strftime("%Y-%m-%d-%H.%M.%S")}.xlsx"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def pg_respond_show(object = nil)
|
121
|
+
respond_to do |format|
|
122
|
+
format.json { render json: object || instancia_modelo }
|
123
|
+
format.html
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def pg_respond_destroy(model, redirect_url = nil)
|
128
|
+
if destroy_model(model)
|
129
|
+
respond_to do |format|
|
130
|
+
format.html do
|
131
|
+
if redirect_url.present?
|
132
|
+
redirect_to redirect_url, notice: 'Elemento borrado.', status: 303
|
133
|
+
else
|
134
|
+
redirect_back(fallback_location: root_path, notice: 'Elemento borrado.', status: 303)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
format.json { head :no_content }
|
138
|
+
end
|
139
|
+
else
|
140
|
+
respond_to do |format|
|
141
|
+
format.html do
|
142
|
+
if model.respond_to?(:associated_elements) && model.associated_elements.present?
|
143
|
+
@model = model
|
144
|
+
render destroy_error_details_view
|
145
|
+
else
|
146
|
+
flash[:error] = @error_message
|
147
|
+
# if redirect_url.present?
|
148
|
+
# redirect_to redirect_url
|
149
|
+
# else
|
150
|
+
redirect_back(fallback_location: root_path, status: 303)
|
151
|
+
# end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
format.json { render json: { error: @error_message }, status: :unprocessable_entity }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# destroy_and_respond DEPRECADO
|
160
|
+
alias_method :destroy_and_respond, :pg_respond_destroy
|
161
|
+
|
162
|
+
def destroy_error_details_view
|
163
|
+
'destroy_error_details'
|
164
|
+
end
|
165
|
+
|
166
|
+
def destroy_model(model)
|
167
|
+
@error_message = 'No se pudo eliminar el registro'
|
168
|
+
begin
|
169
|
+
destroy_method = model.respond_to?(:discard) ? :discard : :destroy
|
170
|
+
return true if model.send(destroy_method)
|
171
|
+
|
172
|
+
@error_message = model.errors.full_messages.join(', ')
|
173
|
+
false
|
174
|
+
rescue ActiveRecord::InvalidForeignKey => e
|
175
|
+
# class_name = /from table \"(?<table_name>[\p{L}_]*)\"/.match(e.message)[:table_name].singularize.camelcase
|
176
|
+
# # pk_id = /from table \"(?<pk_id>[\p{L}_]*)\"/.match(e.message)[:pk_id].singularize.camelcase
|
177
|
+
# clazz = Object.const_get class_name
|
178
|
+
# objects = clazz.where(model.class.table_name.singularize => model)
|
179
|
+
model_name = t("activerecord.models.#{model.class.name.underscore}")
|
180
|
+
@error_message = "#{model_name} no se pudo borrar porque tiene elementos asociados."
|
181
|
+
logger.debug e.message
|
182
|
+
end
|
183
|
+
false
|
184
|
+
end
|
185
|
+
|
186
|
+
def render_smart_listing
|
187
|
+
raise 'implementar en subclase'
|
188
|
+
end
|
189
|
+
|
190
|
+
def buscar_instancia
|
191
|
+
if Object.const_defined?('FriendlyId') && @clase_modelo.is_a?(FriendlyId)
|
192
|
+
@clase_modelo.friendly.find(params[:id])
|
193
|
+
else
|
194
|
+
@clase_modelo.find(params[:id])
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def set_instancia_modelo
|
199
|
+
if action_name.in? %w[new create]
|
200
|
+
self.instancia_modelo = @clase_modelo.new(modelo_params)
|
201
|
+
else
|
202
|
+
self.instancia_modelo = buscar_instancia
|
203
|
+
|
204
|
+
instancia_modelo.assign_attributes(modelo_params) if action_name.in? %w[update]
|
205
|
+
end
|
206
|
+
|
207
|
+
instancia_modelo.current_user = send(PgRails.configuracion.current_user_method)
|
208
|
+
|
209
|
+
authorize instancia_modelo
|
210
|
+
|
211
|
+
self.instancia_modelo = instancia_modelo.decorate if action_name.in? %w[show edit new]
|
212
|
+
end
|
213
|
+
|
214
|
+
def instancia_modelo=(val)
|
215
|
+
instance_variable_set("@#{nombre_modelo}".to_sym, val)
|
216
|
+
end
|
217
|
+
|
218
|
+
def instancia_modelo
|
219
|
+
instance_variable_get("@#{nombre_modelo}".to_sym)
|
220
|
+
end
|
221
|
+
|
222
|
+
def modelo_params
|
223
|
+
if action_name == 'new'
|
224
|
+
params.permit(atributos_permitidos)
|
225
|
+
else
|
226
|
+
params.require(nombre_modelo).permit(atributos_permitidos)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def nombre_modelo
|
231
|
+
@clase_modelo.name.underscore
|
232
|
+
end
|
233
|
+
|
234
|
+
def default_url_options(options = {})
|
235
|
+
if Rails.env.production?
|
236
|
+
options.merge(protocol: 'https')
|
237
|
+
else
|
238
|
+
options
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def setear_layout
|
243
|
+
if params[:sin_layout] == 'true'
|
244
|
+
false
|
245
|
+
else
|
246
|
+
'application'
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def clase_modelo
|
251
|
+
# agarro la variable o intento con el nombre del controller
|
252
|
+
@clase_modelo ||= self.class.name.singularize.gsub('Controller', '').constantize
|
253
|
+
end
|
254
|
+
|
255
|
+
def filtros_y_policy(campos)
|
256
|
+
@filtros = PgRails::FiltrosBuilder.new(
|
257
|
+
self, clase_modelo, campos
|
258
|
+
)
|
259
|
+
scope = policy_scope(clase_modelo)
|
260
|
+
|
261
|
+
@filtros.filtrar(scope)
|
262
|
+
end
|
263
|
+
|
264
|
+
def do_sort(scope, field, direction)
|
265
|
+
unless scope.model.column_names.include? field.to_s
|
266
|
+
return scope
|
267
|
+
end
|
268
|
+
scope = scope.order(field => direction)
|
269
|
+
instance_variable_set(:"@field", field)
|
270
|
+
instance_variable_set(:"@direction", direction)
|
271
|
+
scope
|
272
|
+
rescue ArgumentError => e
|
273
|
+
Utils::Logueador.warning(e.to_s)
|
274
|
+
scope
|
275
|
+
end
|
276
|
+
|
277
|
+
def sort_collection(scope, options = {})
|
278
|
+
if params[:order_by].present?
|
279
|
+
field = params[:order_by]
|
280
|
+
direction = params[:order_direction]
|
281
|
+
do_sort(scope, field, direction)
|
282
|
+
elsif options[:default].present?
|
283
|
+
field = options[:default].first[0]
|
284
|
+
direction = options[:default].first[1]
|
285
|
+
do_sort(scope, field, direction)
|
286
|
+
else
|
287
|
+
scope
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def fecha_invalida
|
292
|
+
respond_to do |format|
|
293
|
+
format.json do
|
294
|
+
render json: { error: 'Formato de fecha inválido' }, status: :unprocessable_entity
|
295
|
+
end
|
296
|
+
format.js { render inline: 'showToast("error", "Formato de fecha inválido")' }
|
297
|
+
format.html { go_back('Formato de fecha inválido') }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def not_authorized
|
302
|
+
respond_to do |format|
|
303
|
+
format.json do
|
304
|
+
render json: { error: 'Not authorized' }, status: :unprocessable_entity
|
305
|
+
end
|
306
|
+
# format.js { render inline: 'showToast("error", "Formato de fecha inválido")' }
|
307
|
+
format.html { go_back('Not authorized') }
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def go_back(message)
|
312
|
+
flash[:error] = message
|
313
|
+
redirect_back fallback_location: root_path
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
class EditarEnLugarController < ::ApplicationController
|
5
|
+
def actualizar
|
6
|
+
key_modelo = params.keys[1]
|
7
|
+
modelo = Kernel.const_get(key_modelo)
|
8
|
+
objeto = modelo.find params[:id]
|
9
|
+
authorize objeto, :editar_en_lugar?
|
10
|
+
object_params = request.parameters[key_modelo]
|
11
|
+
objeto.current_user = current_user
|
12
|
+
objeto.update(object_params)
|
13
|
+
respond_with_bip(objeto, param: key_modelo)
|
14
|
+
rescue Pundit::NotAuthorizedError
|
15
|
+
objeto.errors.add(:base, 'no autorizado')
|
16
|
+
respond_with_bip(objeto)
|
17
|
+
rescue Pundit::Error => e
|
18
|
+
Rollbar.error(e)
|
19
|
+
logger.error(e.message)
|
20
|
+
objeto.errors.add(:base, e.message)
|
21
|
+
respond_with_bip(objeto)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRails
|
4
|
+
class BaseDecorator < Draper::Decorator
|
5
|
+
include ActionView::Helpers
|
6
|
+
include PrintHelper
|
7
|
+
include FormHelper
|
8
|
+
include Pundit::Authorization
|
9
|
+
|
10
|
+
attr_accessor :output_buffer
|
11
|
+
|
12
|
+
delegate_all
|
13
|
+
|
14
|
+
def as_json(_options = {})
|
15
|
+
object.as_json.tap { |o| o[:to_s] = to_s }
|
16
|
+
end
|
17
|
+
|
18
|
+
# def method_missing(method_name, *args, &block) # rubocop:disable Style/MissingRespondToMissing
|
19
|
+
# valor = object.attributes[method_name.to_s]
|
20
|
+
# return super unless valor.present?
|
21
|
+
|
22
|
+
# if valor.instance_of?(Date)
|
23
|
+
# dmy(valor)
|
24
|
+
# # elsif valor.class == ActiveSupport::TimeWithZone
|
25
|
+
# # dmy_time(valor)
|
26
|
+
# else
|
27
|
+
# super
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
|
31
|
+
def destroy_link(message = '¿Estás seguro?')
|
32
|
+
return unless Pundit.policy!(helpers.send(PgRails.configuracion.current_user_method), object).destroy?
|
33
|
+
|
34
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Eliminar' do
|
35
|
+
helpers.link_to object_url, data: { 'turbo-confirm': message, 'turbo-method': :delete },
|
36
|
+
class: "btn #{_config.clase_botones_chicos} btn-#{_config.boton_destroy}" do
|
37
|
+
helpers.content_tag :span, nil, class: clase_icono(_config.icono_destroy).to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def edit_link(texto = '')
|
43
|
+
return unless Pundit.policy!(helpers.send(PgRails.configuracion.current_user_method), object).edit?
|
44
|
+
|
45
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Editar' do
|
46
|
+
helpers.link_to edit_object_url, data: { turbo_frame: :main },
|
47
|
+
class: "btn #{_config.clase_botones_chicos} btn-#{_config.boton_edit}" do
|
48
|
+
helpers.content_tag(:span, nil, class: clase_icono(_config.icono_edit).to_s) + texto
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def show_link(texto = '')
|
54
|
+
return unless Pundit.policy!(helpers.send(PgRails.configuracion.current_user_method), object).show?
|
55
|
+
|
56
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Ver' do
|
57
|
+
helpers.link_to object_url, data: { turbo_frame: :main },
|
58
|
+
class: "btn #{_config.clase_botones_chicos} btn-#{_config.boton_show}" do
|
59
|
+
helpers.content_tag(:span, nil, class: clase_icono(_config.icono_show).to_s) + texto
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def export_link(url, texto = '')
|
65
|
+
return unless Pundit.policy!(helpers.send(PgRails.configuracion.current_user_method), object).export?
|
66
|
+
|
67
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Exportar' do
|
68
|
+
helpers.content_tag :a, target: '_blank',
|
69
|
+
class: "btn #{_config.clase_botones_chicos} btn-#{_config.boton_export}", href: url_change_format(url) do
|
70
|
+
"#{helpers.content_tag(:span, nil, class: clase_icono('file-earmark-excel-fill'))} #{texto}".html_safe
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def new_link(options = {})
|
76
|
+
return unless Pundit.policy!(helpers.send(PgRails.configuracion.current_user_method), object).new?
|
77
|
+
|
78
|
+
helpers.content_tag :span, rel: :tooltip, title: 'Crear' do
|
79
|
+
helpers.link_to new_object_url, class: "btn #{_config.clase_botones_chicos} btn-primary", remote: options[:remote] do
|
80
|
+
helpers.content_tag(:span, nil,
|
81
|
+
class: clase_icono('plus').to_s) + "<span class='d-none d-sm-inline'> Crear #{object.class.nombre_singular.downcase}</span>".html_safe
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def edit_object_url
|
87
|
+
helpers.url_for([:edit, target_object].flatten)
|
88
|
+
end
|
89
|
+
|
90
|
+
def new_object_url
|
91
|
+
"#{helpers.url_for(target_index)}/new"
|
92
|
+
end
|
93
|
+
|
94
|
+
def object_url
|
95
|
+
helpers.url_for(target_object)
|
96
|
+
end
|
97
|
+
|
98
|
+
def target_object
|
99
|
+
default_module.present? ? [default_module, object] : object
|
100
|
+
end
|
101
|
+
|
102
|
+
def target_index
|
103
|
+
default_module.present? ? [default_module, object.class] : object.class
|
104
|
+
end
|
105
|
+
|
106
|
+
def default_module
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def _config
|
113
|
+
PgRails.configuracion
|
114
|
+
end
|
115
|
+
|
116
|
+
def clase_icono(icono)
|
117
|
+
"#{_config.sistema_iconos} #{_config.sistema_iconos}-#{icono}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|