pg_rails 7.1.1.pre.4 → 7.1.1.pre.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/pg_engine/app/controllers/admin/users_controller.rb +1 -1
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +24 -4
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +7 -2
- data/pg_engine/app/controllers/users/confirmations_controller.rb +1 -1
- data/pg_engine/app/helpers/pg_engine/route_helper.rb +10 -2
- data/pg_engine/app/lib/pg_engine/filtros_builder.rb +23 -21
- data/pg_engine/app/views/admin/eventos/new.html.slim +1 -1
- data/pg_engine/app/views/pg_engine/base/index.html.slim +15 -18
- data/pg_engine/config/locales/es.yml +5 -0
- data/pg_engine/db/seeds.rb +3 -5
- data/pg_engine/lib/pg_engine/email_observer.rb +1 -1
- data/pg_engine/spec/factories/users.rb +2 -2
- data/pg_layout/app/javascript/controllers/filtros_controller.js +2 -0
- data/pg_layout/app/javascript/controllers/index.js +2 -0
- data/pg_layout/app/javascript/controllers/selectize_controller.js +10 -0
- data/pg_layout/app/views/layouts/pg_layout/base.html.slim +4 -0
- data/pg_layout/app/views/pg_layout/_modal_show.html.slim +9 -4
- data/pg_rails/lib/version.rb +1 -1
- data/pg_rails/scss/pg_rails.scss +13 -0
- data/pg_scaffold/lib/generators/pg_scaffold/templates/controller.rb +1 -0
- data/pg_scaffold/lib/generators/pg_slim/templates/index.html.slim +3 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b95efca3ae2b2ec3c5779300bbfd6cc00ba9cac453b4fd07395803eb5010a726
|
4
|
+
data.tar.gz: 87811da5c11b5ec8bfb15e45e8b43ed5c606bceb23804bc473990f9f46ab13ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4da052d189d685cd90c2aed939bfebd8d3e4809f6e3db671d686a034d597b32b03a2f52f3b3413c9277566329822cbf4a520ab33531cc40ef8873a2b8c51850a
|
7
|
+
data.tar.gz: fddd0362fab8db6f74816b583372fbc10fbd4d6ad68f48adbbe635579b28339603e1f09358a16563d9d9e6909573009ec6111c84f50d9c28f109758e402f6495
|
@@ -5,7 +5,7 @@ module PgEngine
|
|
5
5
|
clazz.helper_method :atributos_para_listar
|
6
6
|
clazz.helper_method :atributos_para_mostrar
|
7
7
|
clazz.helper_method :current_page_size
|
8
|
-
clazz.helper_method :
|
8
|
+
clazz.helper_method :show_filters?
|
9
9
|
end
|
10
10
|
|
11
11
|
# Public endpoints
|
@@ -19,6 +19,15 @@ module PgEngine
|
|
19
19
|
|
20
20
|
def index
|
21
21
|
@collection = filtros_y_policy atributos_para_buscar
|
22
|
+
|
23
|
+
shared_context = Ransack::Context.for(clase_modelo)
|
24
|
+
|
25
|
+
@q = @clase_modelo.ransack(params[:q], context: shared_context)
|
26
|
+
# @collection = @q.result(distinct: true)
|
27
|
+
@collection = @collection.joins(shared_context.join_sources)
|
28
|
+
vis = Ransack::Visitor.new.accept(@q.base)
|
29
|
+
@collection = @collection.where(vis)
|
30
|
+
|
22
31
|
@collection = sort_collection(@collection)
|
23
32
|
pg_respond_index
|
24
33
|
end
|
@@ -53,8 +62,17 @@ module PgEngine
|
|
53
62
|
|
54
63
|
protected
|
55
64
|
|
56
|
-
def
|
57
|
-
|
65
|
+
def show_filters?
|
66
|
+
cur_route = pg_current_route
|
67
|
+
idtf = cur_route[:controller] + '#' + cur_route[:action] + '#open-filters'
|
68
|
+
|
69
|
+
if params[:ocultar_filtros]
|
70
|
+
session[idtf] = nil
|
71
|
+
elsif params[:mostrar_filtros]
|
72
|
+
session[idtf] = true
|
73
|
+
end
|
74
|
+
|
75
|
+
session[idtf]
|
58
76
|
end
|
59
77
|
|
60
78
|
def current_page_size
|
@@ -160,7 +178,9 @@ module PgEngine
|
|
160
178
|
end
|
161
179
|
else
|
162
180
|
format.turbo_stream do
|
163
|
-
|
181
|
+
# Esto no es totalmente limpio pero funciona tanto en los listados como en los
|
182
|
+
# modal show
|
183
|
+
render turbo_stream: turbo_stream.remove(model) + turbo_stream.remove_all('.modal')
|
164
184
|
end
|
165
185
|
format.html do
|
166
186
|
redirect_back(fallback_location: root_path, notice: msg, status: 303)
|
@@ -94,6 +94,7 @@ module PgEngine
|
|
94
94
|
@notifications = Current.user.notifications.order(id: :desc)
|
95
95
|
.where(type: 'SimpleUserNotifier::Notification')
|
96
96
|
unseen = @notifications.unseen.any?
|
97
|
+
# FIXME: testear y fixear, buscar el primero que esté present
|
97
98
|
tooltip = @notifications.unseen.map(&:tooltip).first
|
98
99
|
@notifications_bell = NotificationsBellComponent.new(
|
99
100
|
unseen:,
|
@@ -112,8 +113,13 @@ module PgEngine
|
|
112
113
|
|
113
114
|
protected
|
114
115
|
|
115
|
-
# rubocop:disable Metrics/AbcSize
|
116
116
|
def render_my_component(component, status)
|
117
|
+
# Esto es para que saltee los turbo frames y genere
|
118
|
+
# un full reload. El turbo_no_cache no es estrictamente necesario
|
119
|
+
# pero lo dejo por las dudas
|
120
|
+
@turbo_page_requires_reload = true
|
121
|
+
@turbo_no_cache = true
|
122
|
+
|
117
123
|
respond_to do |format|
|
118
124
|
format.html do
|
119
125
|
render component.alert_wrapped(view_context),
|
@@ -139,7 +145,6 @@ module PgEngine
|
|
139
145
|
end
|
140
146
|
end
|
141
147
|
end
|
142
|
-
# rubocop:enable Metrics/AbcSize
|
143
148
|
|
144
149
|
def not_authorized(_arg_required_for_active_admin)
|
145
150
|
respond_to do |format|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Users
|
2
2
|
class ConfirmationsController < Devise::ConfirmationsController
|
3
3
|
# GET /resource/confirmation?confirmation_token=abcdef
|
4
|
-
def show
|
4
|
+
def show
|
5
5
|
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
6
6
|
yield resource if block_given?
|
7
7
|
|
@@ -16,11 +16,15 @@ module PgEngine
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.current_route(context)
|
20
|
+
req = request(context)
|
21
|
+
Rails.application.routes.recognize_path(req.path, method: req.env['REQUEST_METHOD'])
|
22
|
+
end
|
23
|
+
|
19
24
|
def self.namespace(context)
|
20
25
|
return Current.namespace if Current.namespace.present?
|
21
26
|
|
22
|
-
|
23
|
-
route = Rails.application.routes.recognize_path(req.path, method: req.env['REQUEST_METHOD'])
|
27
|
+
route = current_route(context)
|
24
28
|
parts = route[:controller].split('/')
|
25
29
|
return unless parts.length > 1
|
26
30
|
|
@@ -30,6 +34,10 @@ module PgEngine
|
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
37
|
+
def pg_current_route
|
38
|
+
NamespaceDeductor.current_route(self)
|
39
|
+
end
|
40
|
+
|
33
41
|
def pg_namespace
|
34
42
|
NamespaceDeductor.namespace(self)
|
35
43
|
end
|
@@ -186,6 +186,9 @@ module PgEngine
|
|
186
186
|
end
|
187
187
|
|
188
188
|
def filtros_html(options = {})
|
189
|
+
@form = options[:form]
|
190
|
+
raise PgEngine::Error, 'se debe setear el form' if @form.blank?
|
191
|
+
|
189
192
|
res = ''
|
190
193
|
@filtros.each do |campo, opciones|
|
191
194
|
if opciones[:oculto] ||
|
@@ -253,42 +256,35 @@ module PgEngine
|
|
253
256
|
|
254
257
|
map = scope.map { |o| [o.to_s, o.id] }
|
255
258
|
|
256
|
-
unless @filtros[campo.to_sym].present? && @filtros[campo.to_sym][:include_blank] == false
|
257
|
-
map.unshift ["Seleccionar #{@clase_modelo.human_attribute_name(campo.to_sym).downcase}",
|
258
|
-
nil]
|
259
|
-
end
|
260
|
-
|
261
|
-
default = parametros_controller[campo].nil? ? nil : parametros_controller[campo]
|
262
259
|
content_tag :div, class: 'col-auto' do
|
263
260
|
content_tag :div, class: 'filter' do
|
264
261
|
if multiple
|
265
|
-
|
266
|
-
|
262
|
+
@form.select campo, map, { multiple: true }, 'data-controller': 'selectize',
|
263
|
+
class: 'form-select form-select-sm pg-input-lg'
|
267
264
|
else
|
268
|
-
|
269
|
-
|
265
|
+
campo = campo.to_s + '_id_in'
|
266
|
+
placeholder = ransack_placeholder(campo)
|
267
|
+
@form.select campo, map, { multiple: true }, placeholder:, 'data-controller': 'selectize',
|
268
|
+
class: 'form-control form-control-sm pg-input-lg'
|
270
269
|
end
|
271
270
|
end
|
272
271
|
end
|
273
272
|
end
|
274
273
|
|
275
274
|
def filtro_select(campo, placeholder = '')
|
276
|
-
map = @clase_modelo.send(campo).values.map do |key|
|
275
|
+
map = @clase_modelo.send(sin_sufijo(campo)).values.map do |key|
|
277
276
|
[I18n.t("#{@clase_modelo.to_s.underscore}.#{campo}.#{key}", default: key.humanize),
|
278
277
|
key.value]
|
279
278
|
end
|
280
|
-
unless @filtros[campo.to_sym].present? && @filtros[campo.to_sym][:include_blank] == false
|
281
|
-
map.unshift ["Seleccionar #{placeholder.downcase}",
|
282
|
-
nil]
|
283
|
-
end
|
284
|
-
default = parametros_controller[campo].nil? ? nil : parametros_controller[campo]
|
285
279
|
content_tag :div, class: 'col-auto' do
|
286
280
|
content_tag :div, class: 'filter' do
|
287
|
-
|
281
|
+
placeholder = ransack_placeholder(campo)
|
282
|
+
@form.select(campo, map, { multiple: true }, placeholder:, class: 'form-control form-control-sm pg-input-lg', 'data-controller': 'selectize')
|
288
283
|
end
|
289
284
|
end
|
290
285
|
end
|
291
286
|
|
287
|
+
# DEPRECADO
|
292
288
|
def filtro_select_custom(campo, placeholder = '')
|
293
289
|
map = @filtros[campo.to_sym][:opciones]
|
294
290
|
unless @filtros[campo.to_sym].present? && @filtros[campo.to_sym][:include_blank] == false
|
@@ -306,8 +302,9 @@ module PgEngine
|
|
306
302
|
def filtro_texto(campo, placeholder = '')
|
307
303
|
content_tag :div, class: 'col-auto' do
|
308
304
|
content_tag :div, class: 'filter' do
|
309
|
-
|
310
|
-
|
305
|
+
placeholder = ransack_placeholder(campo)
|
306
|
+
@form.search_field(
|
307
|
+
campo, class: 'form-control form-control-sm allow-enter-submit', placeholder:, autocomplete: 'off'
|
311
308
|
)
|
312
309
|
end
|
313
310
|
end
|
@@ -330,14 +327,19 @@ module PgEngine
|
|
330
327
|
def filtro_fecha(campo, placeholder = '')
|
331
328
|
content_tag :div, class: 'col-auto' do
|
332
329
|
content_tag :div, class: 'filter' do
|
330
|
+
placeholder = ransack_placeholder(campo)
|
333
331
|
label_tag(nil, placeholder, class: 'text-body-secondary') +
|
334
|
-
|
335
|
-
campo,
|
332
|
+
@form.date_field(
|
333
|
+
campo, class: 'form-control form-control-sm d-inline-block w-auto ms-1', placeholder:, autocomplete: 'off'
|
336
334
|
)
|
337
335
|
end
|
338
336
|
end
|
339
337
|
end
|
340
338
|
|
339
|
+
def ransack_placeholder(campo)
|
340
|
+
@form.object.translate(campo, include_associations: true)
|
341
|
+
end
|
342
|
+
|
341
343
|
def parametros_controller
|
342
344
|
params
|
343
345
|
end
|
@@ -6,7 +6,7 @@
|
|
6
6
|
= f.input :message, as: :text
|
7
7
|
- else
|
8
8
|
= f.rich_text_area :message
|
9
|
-
= f.input :message_text, as: :text
|
9
|
+
= f.input :message_text, as: :text, hint: 'Solo para emails, para la plain/text part'
|
10
10
|
= f.input :tooltip
|
11
11
|
= f.input :subject
|
12
12
|
= f.input :record_type
|
@@ -3,37 +3,34 @@
|
|
3
3
|
- @actions&.each do |link_args|
|
4
4
|
= link_to(*link_args)
|
5
5
|
- if @filtros.present?
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
|
14
|
-
span.text Filtrar
|
6
|
+
- if show_filters?
|
7
|
+
= link_to namespaced_path(@clase_modelo, ocultar_filtros: 1),
|
8
|
+
class: 'btn btn-sm btn-outline-primary col-auto' do
|
9
|
+
| Ocultar filtros
|
10
|
+
- else
|
11
|
+
= link_to namespaced_path(@clase_modelo, mostrar_filtros: 1),
|
12
|
+
class: 'btn btn-sm btn-outline-primary col-auto' do
|
13
|
+
| Filtrar
|
15
14
|
.ms-1
|
16
15
|
= @clase_modelo.new.decorate.new_link
|
17
16
|
|
18
|
-
- if @filtros.present?
|
19
|
-
.
|
17
|
+
- if @filtros.present? && show_filters?
|
18
|
+
.border-bottom#filtros
|
20
19
|
.d-flex.align-items-center.p-2
|
21
20
|
.px-2.d-none.d-sm-inline-block
|
22
21
|
span.bi.bi-funnel-fill
|
23
|
-
=
|
22
|
+
= search_form_for @q, url: namespaced_path(@clase_modelo) do |f|
|
24
23
|
.row.g-1
|
25
|
-
= @filtros.filtros_html
|
26
|
-
.col-auto
|
24
|
+
= @filtros.filtros_html(form: f)
|
25
|
+
.col-auto.gap-1.d-flex.align-items-start
|
27
26
|
= button_tag class: 'btn btn-sm btn-primary col-auto' do
|
28
27
|
span.bi.bi-search
|
29
28
|
span.d-none.d-sm-inline
|
30
29
|
|  
|
31
30
|
span.text Buscar
|
32
|
-
|
33
|
-
= link_to namespaced_path(@clase_modelo, clean: true),
|
31
|
+
= link_to namespaced_path(@clase_modelo, mostrar_filtros: 1),
|
34
32
|
class: 'btn btn-sm btn-secondary col-auto' do
|
35
33
|
| Limpiar
|
36
|
-
|
37
34
|
div
|
38
35
|
- if @collection.any?
|
39
36
|
.table-responsive
|
@@ -67,7 +64,7 @@ div
|
|
67
64
|
= t(i18n_key, default: :'.empty_but_filtered', model: @clase_modelo.nombre_plural.downcase)
|
68
65
|
| :
|
69
66
|
span.ms-2
|
70
|
-
= link_to namespaced_path(@clase_modelo,
|
67
|
+
= link_to namespaced_path(@clase_modelo, mostrar_filtros: 1) do
|
71
68
|
| Limpiar búsqueda
|
72
69
|
- else
|
73
70
|
- i18n_key = "#{controller_key}.#{action_name}.index.empty"
|
data/pg_engine/db/seeds.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
DatabaseCleaner.clean_with(:truncation, except: %w(ar_internal_metadata))
|
2
2
|
|
3
|
-
|
3
|
+
FactoryBot.create :user, email: 'mrosso10@gmail.com', nombre: 'Martín', apellido: 'Rosso', password: 'admin123',
|
4
|
+
confirmed_at: Time.now, developer: true
|
4
5
|
|
5
|
-
|
6
|
-
FactoryBot.create :user, email: MAIL, nombre: 'Martín', apellido: 'Rosso', password: 'admin123',
|
7
|
-
confirmed_at: Time.now, developer: true
|
8
|
-
end
|
6
|
+
Account.first.users << FactoryBot.create(:user, orphan: true)
|
@@ -37,8 +37,8 @@
|
|
37
37
|
|
38
38
|
FactoryBot.define do
|
39
39
|
factory :user, class: 'User' do
|
40
|
-
nombre { Faker::Name.
|
41
|
-
apellido { Faker::Name.
|
40
|
+
nombre { Faker::Name.first_name }
|
41
|
+
apellido { Faker::Name.last_name }
|
42
42
|
email { Faker::Internet.email }
|
43
43
|
password { "password#{rand(99_999)}" }
|
44
44
|
confirmed_at { Faker::Date.backward }
|
@@ -8,6 +8,7 @@ import ClearTimeoutController from './clear_timeout_controller'
|
|
8
8
|
import SwitcherController from './switcher_controller'
|
9
9
|
import FiltrosController from './filtros_controller'
|
10
10
|
import NotificationsController from './notifications_controller'
|
11
|
+
import SelectizeController from './selectize_controller'
|
11
12
|
|
12
13
|
application.register('navbar', NavbarController)
|
13
14
|
application.register('nested', NestedController)
|
@@ -17,5 +18,6 @@ application.register('clear-timeout', ClearTimeoutController)
|
|
17
18
|
application.register('switcher', SwitcherController)
|
18
19
|
application.register('filtros', FiltrosController)
|
19
20
|
application.register('notifications', NotificationsController)
|
21
|
+
application.register('selectize', SelectizeController)
|
20
22
|
|
21
23
|
// TODO: testear con capybara todo lo que se pueda
|
@@ -5,6 +5,9 @@ html
|
|
5
5
|
meta charset="UTF-8"
|
6
6
|
meta http-equiv="X-UA-Compatible" content="IE=edge"
|
7
7
|
meta name="viewport" content="width=device-width,initial-scale=1"
|
8
|
+
- if @turbo_page_requires_reload
|
9
|
+
meta name="turbo-visit-control" content="reload"
|
10
|
+
|
8
11
|
- cache :title_icon
|
9
12
|
title = t('app_name')
|
10
13
|
- begin
|
@@ -71,6 +74,7 @@ html
|
|
71
74
|
= render FlashContainerComponent.new
|
72
75
|
/ TODO: si hay varios flashes toast, se superponen. habría que
|
73
76
|
hacer un container con position absolute para los toasts
|
77
|
+
/ FIXME: el yield(filtros)
|
74
78
|
= content
|
75
79
|
div style="width:100%; height: 10em"
|
76
80
|
= render partial: 'layouts/footer'
|
@@ -1,9 +1,14 @@
|
|
1
|
-
.modal.modal-lg.modal-asociable[tabindex="-1" data-controller="modal"
|
1
|
+
.modal.modal-lg.modal-asociable[tabindex="-1" data-controller="modal"
|
2
|
+
data-remove-on-hide="true" data-turbo-temporary="true"]
|
2
3
|
.modal-dialog
|
3
4
|
.modal-content
|
4
5
|
.modal-header
|
5
|
-
.
|
6
|
-
|
6
|
+
= link_to object.target_object do
|
7
|
+
| Ir al #{object.class.nombre_singular.downcase}
|
7
8
|
a.btn-close[type="button" data-bs-dismiss="modal" aria-label="Close"]
|
8
9
|
.modal-body
|
9
|
-
=
|
10
|
+
= turbo_frame_tag :modal_generic, target: :_top do
|
11
|
+
.float-end
|
12
|
+
= object.edit_link
|
13
|
+
= object.destroy_link
|
14
|
+
= render object
|
data/pg_rails/lib/version.rb
CHANGED
data/pg_rails/scss/pg_rails.scss
CHANGED
@@ -39,7 +39,20 @@ $alert-margin-bottom: 0.5rem;
|
|
39
39
|
@import 'bootstrap-icons/font/bootstrap-icons';
|
40
40
|
|
41
41
|
@import 'trix/dist/trix';
|
42
|
+
@import 'tom-select/dist/scss/tom-select.bootstrap5';
|
42
43
|
|
44
|
+
.ts-control {
|
45
|
+
padding-top: 2px!important;
|
46
|
+
padding-bottom: 2px!important;
|
47
|
+
display: flex;
|
48
|
+
gap: 4px;
|
49
|
+
}
|
50
|
+
.input-group-sm > .ts-wrapper.multi.has-items .ts-control, .ts-wrapper.form-select-sm.multi.has-items .ts-control, .ts-wrapper.form-control-sm.multi.has-items .ts-control {
|
51
|
+
padding-top: 2px!important;
|
52
|
+
}
|
53
|
+
.ts-wrapper.multi .ts-control > div {
|
54
|
+
margin: 0!important;
|
55
|
+
}
|
43
56
|
$warning-border-emphasis: shade-color($yellow, 60%);
|
44
57
|
.bg-primary-subtle .btn-warning {
|
45
58
|
border: 1px solid $warning-border-emphasis;
|
@@ -9,7 +9,8 @@
|
|
9
9
|
= @clase_modelo.new.decorate.new_link
|
10
10
|
.ms-1
|
11
11
|
= @clase_modelo.new.decorate.export_link(request.url)
|
12
|
-
|
12
|
+
/ FIXME: update
|
13
|
+
.collapse.p-2.border-bottom#filtros class="#{ 'show' if show_filters? }"
|
13
14
|
.d-flex.align-items-center
|
14
15
|
.px-2.d-none.d-sm-inline-block
|
15
16
|
span.bi.bi-funnel-fill
|
@@ -20,7 +21,7 @@
|
|
20
21
|
= button_tag class: 'btn btn-sm btn-primary col-auto' do
|
21
22
|
span.bi.bi-search
|
22
23
|
.col-auto
|
23
|
-
= link_to <%= plural_route_name %>_path(
|
24
|
+
= link_to <%= plural_route_name %>_path(mostrar_filtros: true),
|
24
25
|
class: 'btn btn-sm btn-secondary col-auto' do
|
25
26
|
| Limpiar
|
26
27
|
|
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.1.pre.
|
4
|
+
version: 7.1.1.pre.6
|
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-07-
|
11
|
+
date: 2024-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -814,6 +814,7 @@ files:
|
|
814
814
|
- pg_layout/app/javascript/controllers/nested_controller.js
|
815
815
|
- pg_layout/app/javascript/controllers/notifications_controller.js
|
816
816
|
- pg_layout/app/javascript/controllers/pg_form_controller.js
|
817
|
+
- pg_layout/app/javascript/controllers/selectize_controller.js
|
817
818
|
- pg_layout/app/javascript/controllers/switcher_controller.js
|
818
819
|
- pg_layout/app/javascript/utils/cookies.js
|
819
820
|
- pg_layout/app/javascript/utils/utils.ts
|