pg_rails 7.0.8.pre.alpha.13 → 7.0.8.pre.alpha.14
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 +4 -4
- data/pg_engine/app/controllers/admin/accounts_controller.rb +2 -0
- data/pg_engine/app/controllers/admin/user_accounts_controller.rb +2 -0
- data/pg_engine/app/controllers/admin/users_controller.rb +2 -0
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +3 -3
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +8 -7
- data/pg_engine/app/helpers/pg_engine/pg_rails_helper.rb +23 -0
- data/pg_engine/app/models/user.rb +18 -3
- data/pg_engine/config/initializers/rollbar.rb +78 -0
- data/pg_engine/db/seeds.rb +1 -1
- data/pg_engine/lib/pg_engine/utils/pg_logger.rb +47 -25
- data/pg_engine/lib/tasks/auto_anotar_modelos.rake +1 -3
- data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/concerns/pg_engine/resource_helper_spec.rb +67 -0
- data/pg_engine/spec/factories/users.rb +1 -8
- data/pg_engine/spec/helpers/pg_engine/pg_rails_helper_spec.rb +38 -0
- data/pg_engine/spec/lib/pg_engine/utils/pg_engine/pg_logger_spec.rb +38 -0
- data/pg_engine/spec/models/user_spec.rb +39 -0
- data/pg_layout/app/assets/stylesheets/animations.scss +26 -0
- data/pg_layout/app/javascript/fadein_onload_controller.js +20 -0
- data/pg_layout/app/javascript/utils.ts +24 -0
- data/pg_layout/app/views/layouts/pg_layout/layout.html.slim +2 -0
- data/pg_layout/app/views/pg_layout/_rollbar.html.erb +28 -0
- data/pg_layout/index.js +2 -0
- data/pg_rails/lib/pg_rails/vcr_support.rb +21 -0
- data/pg_rails/lib/version.rb +1 -1
- data/pg_rails/scss/pg_rails.scss +1 -0
- data/pg_scaffold/lib/generators/pg_scaffold/templates/controller.rb +2 -0
- data/pg_scaffold/spec/generators_spec.rb +1 -1
- metadata +11 -3
- /data/pg_engine/spec/{controllers/concerns → lib}/pg_engine/error_helper_spec.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a52205bc09a4d6de1b93e6a4272110bc740bfc72a1bb9cb306d0e4f3d7684e19
|
4
|
+
data.tar.gz: 49606131fec5b3933957c43d8ab29cf853a0b1a8944a27fa7527c8669a3ca46c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8beb180af71e265ec1d027666267628fa699904a560ed6e224deaf3009b7230f8b72520799e2b8465ed709b92f33f0eac81f4e61cd2777489e2a59f5a6e25cc
|
7
|
+
data.tar.gz: 5e4b1e3869550430832bae5bd5f0c205a94a5a16a41dd898e14f47fd9b786fa4c7d097f9c94a771379757b5b85752cc3adf823e7b294a74e51321f58a779124c
|
@@ -210,7 +210,7 @@ module PgEngine
|
|
210
210
|
def buscar_instancia
|
211
211
|
if Object.const_defined?('FriendlyId') && @clase_modelo.is_a?(FriendlyId)
|
212
212
|
@clase_modelo.friendly.find(params[:id])
|
213
|
-
elsif @clase_modelo.respond_to? :find_by_hashid
|
213
|
+
elsif @clase_modelo.respond_to? :find_by_hashid!
|
214
214
|
# rubocop:disable Rails/DynamicFindBy
|
215
215
|
@clase_modelo.find_by_hashid!(params[:id])
|
216
216
|
# rubocop:enable Rails/DynamicFindBy
|
@@ -273,7 +273,7 @@ module PgEngine
|
|
273
273
|
|
274
274
|
def do_sort(scope, field, direction)
|
275
275
|
unless scope.model.column_names.include? field.to_s
|
276
|
-
PgLogger.
|
276
|
+
PgLogger.warn("No existe el campo \"#{field}\"", :warn)
|
277
277
|
return scope
|
278
278
|
end
|
279
279
|
scope = scope.order(field => direction)
|
@@ -281,7 +281,7 @@ module PgEngine
|
|
281
281
|
instance_variable_set(:@direction, direction)
|
282
282
|
scope
|
283
283
|
rescue ArgumentError => e
|
284
|
-
PgLogger.
|
284
|
+
PgLogger.warn(e, :warn)
|
285
285
|
scope
|
286
286
|
end
|
287
287
|
|
@@ -40,13 +40,14 @@ module PgEngine
|
|
40
40
|
|
41
41
|
protected
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
43
|
+
# TODO: ver qué pasa en producción
|
44
|
+
# def default_url_options(options = {})
|
45
|
+
# if Rails.env.production?
|
46
|
+
# options.merge(protocol: 'https')
|
47
|
+
# else
|
48
|
+
# options
|
49
|
+
# end
|
50
|
+
# end
|
50
51
|
|
51
52
|
def fecha_invalida
|
52
53
|
respond_to do |format|
|
@@ -7,5 +7,28 @@ module PgEngine
|
|
7
7
|
def current_account
|
8
8
|
current_user&.current_account
|
9
9
|
end
|
10
|
+
|
11
|
+
def img_placeholder(src = nil, width: '100%', height: '100%', fade_in: false, **img_opts)
|
12
|
+
if fade_in || src.nil?
|
13
|
+
img_opts = img_opts.merge(style: [img_opts[:style], 'display:none'].compact.join(';'))
|
14
|
+
do_placeholder(src, width:, height:, **img_opts)
|
15
|
+
else
|
16
|
+
image_tag src, **img_opts
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def do_placeholder(src = nil, width: '100%', height: '100%', **img_opts)
|
23
|
+
content_tag('div', class: 'placeholder-glow') do
|
24
|
+
content_tag('div', class: 'placeholder', style: "width: #{width}; height: #{height}") do
|
25
|
+
if src.present?
|
26
|
+
image_tag src,
|
27
|
+
'data-controller': 'fadein_onload',
|
28
|
+
**img_opts
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
10
33
|
end
|
11
34
|
end
|
@@ -27,10 +27,8 @@
|
|
27
27
|
# created_at :datetime not null
|
28
28
|
# updated_at :datetime not null
|
29
29
|
#
|
30
|
-
class User < ApplicationRecord
|
31
|
-
# ApplicationRecord should be defined on Application
|
32
30
|
|
33
|
-
|
31
|
+
class User < ApplicationRecord
|
34
32
|
devise :database_authenticatable, :registerable,
|
35
33
|
:recoverable, :rememberable,
|
36
34
|
:lockable, :timeoutable, :trackable, :confirmable
|
@@ -51,6 +49,19 @@ class User < ApplicationRecord
|
|
51
49
|
validates_length_of :password, if: :password_required?, within: 6..128,
|
52
50
|
message: 'es demasiado corta (6 caracteres mínimo)'
|
53
51
|
|
52
|
+
attr_accessor :orphan
|
53
|
+
|
54
|
+
after_create do
|
55
|
+
# TODO: si fue invitado, sumar a la account del invitador
|
56
|
+
create_account unless orphan
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_account
|
60
|
+
account = Account.create(nombre: email, plan: 0)
|
61
|
+
ua = user_accounts.create(account:)
|
62
|
+
raise(ActiveRecord::Rollback) unless ua.persisted?
|
63
|
+
end
|
64
|
+
|
54
65
|
def password_required?
|
55
66
|
!persisted? || !password.nil? || !password_confirmation.nil?
|
56
67
|
end
|
@@ -65,7 +76,11 @@ class User < ApplicationRecord
|
|
65
76
|
"#{nombre} #{apellido}"
|
66
77
|
end
|
67
78
|
|
79
|
+
class Error < StandardError; end
|
80
|
+
|
68
81
|
def current_account
|
82
|
+
raise Error, 'El usuario debe tener cuenta' if accounts.empty?
|
83
|
+
|
69
84
|
accounts.first
|
70
85
|
end
|
71
86
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
Rollbar.configure do |config|
|
2
|
+
# Without configuration, Rollbar is enabled in all environments.
|
3
|
+
# To disable in specific environments, set config.enabled=false.
|
4
|
+
|
5
|
+
config.access_token = ENV['ROLLBAR_ACCESS_TOKEN']
|
6
|
+
|
7
|
+
# Here we'll disable in 'test':
|
8
|
+
if Rails.env.test?
|
9
|
+
config.enabled = false
|
10
|
+
end
|
11
|
+
|
12
|
+
# By default, Rollbar will try to call the `current_user` controller method
|
13
|
+
# to fetch the logged-in user object, and then call that object's `id`
|
14
|
+
# method to fetch this property. To customize:
|
15
|
+
# config.person_method = "my_current_user"
|
16
|
+
# config.person_id_method = "my_id"
|
17
|
+
|
18
|
+
# Additionally, you may specify the following:
|
19
|
+
# config.person_username_method = "username"
|
20
|
+
# config.person_email_method = "email"
|
21
|
+
|
22
|
+
# If you want to attach custom data to all exception and message reports,
|
23
|
+
# provide a lambda like the following. It should return a hash.
|
24
|
+
# config.custom_data_method = lambda { {:some_key => "some_value" } }
|
25
|
+
|
26
|
+
# Add exception class names to the exception_level_filters hash to
|
27
|
+
# change the level that exception is reported at. Note that if an exception
|
28
|
+
# has already been reported and logged the level will need to be changed
|
29
|
+
# via the rollbar interface.
|
30
|
+
# Valid levels: 'critical', 'error', 'warning', 'info', 'debug', 'ignore'
|
31
|
+
# 'ignore' will cause the exception to not be reported at all.
|
32
|
+
# config.exception_level_filters.merge!('MyCriticalException' => 'critical')
|
33
|
+
#
|
34
|
+
# You can also specify a callable, which will be called with the exception instance.
|
35
|
+
# config.exception_level_filters.merge!('MyCriticalException' => lambda { |e| 'critical' })
|
36
|
+
|
37
|
+
config.exception_level_filters.merge!({
|
38
|
+
'ActionController::RoutingError' => 'ignore',
|
39
|
+
'ActionDispatch::Http::MimeNegotiation::InvalidType' => 'ignore',
|
40
|
+
'MailDeliveryTemporalError' => 'warning',
|
41
|
+
})
|
42
|
+
|
43
|
+
|
44
|
+
# Enable asynchronous reporting (uses girl_friday or Threading if girl_friday
|
45
|
+
# is not installed)
|
46
|
+
# config.use_async = true
|
47
|
+
# Supply your own async handler:
|
48
|
+
# config.async_handler = Proc.new { |payload|
|
49
|
+
# Thread.new { Rollbar.process_from_async_handler(payload) }
|
50
|
+
# }
|
51
|
+
|
52
|
+
# Enable asynchronous reporting (using sucker_punch)
|
53
|
+
# config.use_sucker_punch
|
54
|
+
|
55
|
+
# Enable delayed reporting (using Sidekiq)
|
56
|
+
# config.use_sidekiq
|
57
|
+
# You can supply custom Sidekiq options:
|
58
|
+
# config.use_sidekiq 'queue' => 'default'
|
59
|
+
|
60
|
+
# If your application runs behind a proxy server, you can set proxy parameters here.
|
61
|
+
# If https_proxy is set in your environment, that will be used. Settings here have precedence.
|
62
|
+
# The :host key is mandatory and must include the URL scheme (e.g. 'http://'), all other fields
|
63
|
+
# are optional.
|
64
|
+
#
|
65
|
+
# config.proxy = {
|
66
|
+
# host: 'http://some.proxy.server',
|
67
|
+
# port: 80,
|
68
|
+
# user: 'username_if_auth_required',
|
69
|
+
# password: 'password_if_auth_required'
|
70
|
+
# }
|
71
|
+
|
72
|
+
# If you run your staging application instance in production environment then
|
73
|
+
# you'll want to override the environment reported by `Rails.env` with an
|
74
|
+
# environment variable like this: `ROLLBAR_ENV=staging`. This is a recommended
|
75
|
+
# setup for Heroku. See:
|
76
|
+
# https://devcenter.heroku.com/articles/deploying-to-a-custom-rails-environment
|
77
|
+
config.environment = ENV['ROLLBAR_ENV'].presence || Rails.env
|
78
|
+
end
|
data/pg_engine/db/seeds.rb
CHANGED
@@ -2,42 +2,64 @@
|
|
2
2
|
|
3
3
|
require 'rainbow'
|
4
4
|
|
5
|
+
def pg_warn(obj, type = :error)
|
6
|
+
PgEngine::PgLogger.warn(obj, type)
|
7
|
+
end
|
8
|
+
|
5
9
|
module PgEngine
|
6
10
|
class PgLogger
|
7
11
|
class << self
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
# DEPRECATED
|
13
|
+
# Muestro el caller[1] para saber dónde se llamó a la función deprecada
|
14
|
+
# def deprecated(mensaje)
|
15
|
+
# titulo = Rainbow(" WARNING en #{caller[1]}").yellow.bold
|
16
|
+
# detalles = Rainbow(" #{mensaje}").yellow
|
17
|
+
# Rails.logger.warn("#{titulo}\n#{detalles}")
|
18
|
+
# Rollbar.warning("#{mensaje}\n\n#{caller.join("\n")}")
|
19
|
+
# end
|
20
|
+
|
21
|
+
def warn(obj, type = :error)
|
22
|
+
mensaje = if obj.is_a? Exception
|
23
|
+
obj.full_message.lines.first
|
24
|
+
else
|
25
|
+
obj
|
26
|
+
end
|
27
|
+
notify(mensaje, type)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def notify(mensaje, type)
|
33
|
+
Rails.logger.send(type, titulo(mensaje, type))
|
34
|
+
Rails.logger.send(type, detalles(type))
|
35
|
+
Rollbar.send(type, "#{mensaje}\n\n#{bktrc.join("\n")}")
|
36
|
+
nil
|
13
37
|
end
|
14
38
|
|
15
|
-
def
|
16
|
-
|
17
|
-
detalles = Rainbow(" #{exception.message}").red
|
18
|
-
Rails.logger.error("#{titulo}\n#{detalles}")
|
19
|
-
Rollbar.error(exception)
|
39
|
+
def titulo(mensaje, type)
|
40
|
+
Rainbow(mensaje).bold.send(color_for(type))
|
20
41
|
end
|
21
42
|
|
22
|
-
def
|
23
|
-
|
24
|
-
detalles = Rainbow(" #{mensaje}").red
|
25
|
-
Rails.logger.error("#{titulo}\n#{detalles}")
|
26
|
-
Rollbar.error("#{mensaje}\n\n#{caller.join("\n")}")
|
43
|
+
def detalles(type)
|
44
|
+
Rainbow("#{type.to_s.upcase} logueado en #{bktrc[0]}").send(color_for(type))
|
27
45
|
end
|
28
46
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
47
|
+
def bktrc
|
48
|
+
bc = ActiveSupport::BacktraceCleaner.new
|
49
|
+
bc.add_filter { |line| line.gsub(%r{.*pg_rails/}, '') }
|
50
|
+
bc.add_silencer { |line| /pg_logger/.match?(line) }
|
51
|
+
bc.clean(caller)
|
34
52
|
end
|
35
53
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
54
|
+
def color_for(type)
|
55
|
+
case type
|
56
|
+
when :info
|
57
|
+
:blue
|
58
|
+
when :warn
|
59
|
+
:yellow
|
60
|
+
else # :error
|
61
|
+
:red
|
62
|
+
end
|
41
63
|
end
|
42
64
|
end
|
43
65
|
end
|
@@ -6,7 +6,7 @@ Dotenv.load
|
|
6
6
|
model_paths = begin
|
7
7
|
JSON.parse(ENV['MODEL_PATHS'])
|
8
8
|
rescue JSON::ParserError
|
9
|
-
ENV['MODEL_PATHS']
|
9
|
+
ENV['MODEL_PATHS'] || 'app/models'
|
10
10
|
end
|
11
11
|
|
12
12
|
if Rails.env.development?
|
@@ -30,8 +30,6 @@ if Rails.env.development?
|
|
30
30
|
'show_indexes' => 'false',
|
31
31
|
'simple_indexes' => 'true',
|
32
32
|
'model_dir' => model_paths,
|
33
|
-
# 'model_dir' => ['app/models', 'app/overrides'],
|
34
|
-
# 'model_dir' => 'app/models',
|
35
33
|
'root_dir' => '',
|
36
34
|
'include_version' => 'false',
|
37
35
|
'require' => '',
|
@@ -29,9 +29,9 @@ require 'rails_helper'
|
|
29
29
|
|
30
30
|
RSpec.describe Admin::UserAccountsController do
|
31
31
|
render_views
|
32
|
-
let(:user) { create :
|
32
|
+
let!(:user) { create :user }
|
33
33
|
|
34
|
-
let(:account) { create :account }
|
34
|
+
let!(:account) { create :account }
|
35
35
|
|
36
36
|
# This should return the minimal set of attributes required to create a valid
|
37
37
|
# UserAccount. As you add validations to UserAccount, be sure to
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe PgEngine::Resource do
|
4
|
+
let(:instancia) { Admin::CategoriaDeCosasController.new }
|
5
|
+
|
6
|
+
describe '#buscar_instancia' do
|
7
|
+
subject do
|
8
|
+
instancia.send(:buscar_instancia)
|
9
|
+
end
|
10
|
+
|
11
|
+
let!(:categoria_de_cosa) { create :categoria_de_cosa }
|
12
|
+
let(:request) { double }
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(request).to receive_messages(filtered_parameters: { id: categoria_de_cosa.to_param },
|
16
|
+
parameters: { id: categoria_de_cosa.to_param })
|
17
|
+
allow(instancia).to receive(:request).and_return(request)
|
18
|
+
instancia.set_clase_modelo
|
19
|
+
end
|
20
|
+
|
21
|
+
it do
|
22
|
+
allow(CategoriaDeCosa).to receive(:find_by_hashid!)
|
23
|
+
subject
|
24
|
+
expect(CategoriaDeCosa).to have_received(:find_by_hashid!)
|
25
|
+
end
|
26
|
+
|
27
|
+
it do
|
28
|
+
expect(subject).to eq categoria_de_cosa
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#do_sort' do
|
33
|
+
subject do
|
34
|
+
instancia.send(:do_sort, scope, param, direction)
|
35
|
+
end
|
36
|
+
|
37
|
+
let!(:categoria_de_cosa_ult) { create :categoria_de_cosa, nombre: 'Z' }
|
38
|
+
let!(:categoria_de_cosa_pri) { create :categoria_de_cosa, nombre: 'a' }
|
39
|
+
let(:scope) { CategoriaDeCosa.all }
|
40
|
+
let(:param) { :nombre }
|
41
|
+
let(:direction) { :desc }
|
42
|
+
|
43
|
+
context 'asc' do
|
44
|
+
let(:direction) { :asc }
|
45
|
+
|
46
|
+
it do
|
47
|
+
expect(subject.to_a).to eq [categoria_de_cosa_pri, categoria_de_cosa_ult]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'desc' do
|
52
|
+
let(:direction) { :desc }
|
53
|
+
|
54
|
+
it do
|
55
|
+
expect(subject.to_a).to eq [categoria_de_cosa_ult, categoria_de_cosa_pri]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'cuando no existe el param' do
|
60
|
+
let(:param) { :inexistente }
|
61
|
+
|
62
|
+
it do
|
63
|
+
expect(subject.to_a).to eq [categoria_de_cosa_ult, categoria_de_cosa_pri]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -36,7 +36,7 @@
|
|
36
36
|
#
|
37
37
|
|
38
38
|
FactoryBot.define do
|
39
|
-
factory :
|
39
|
+
factory :user, class: 'User' do
|
40
40
|
nombre { Faker::Name.name }
|
41
41
|
apellido { Faker::Name.name }
|
42
42
|
email { Faker::Internet.email }
|
@@ -50,12 +50,5 @@ FactoryBot.define do
|
|
50
50
|
trait :developer do
|
51
51
|
developer { true }
|
52
52
|
end
|
53
|
-
|
54
|
-
factory :user do
|
55
|
-
after(:create) do |user, _context|
|
56
|
-
account = create :account
|
57
|
-
create :user_account, user:, account:
|
58
|
-
end
|
59
|
-
end
|
60
53
|
end
|
61
54
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
# rubocop:disable RSpec/ExampleLength
|
3
|
+
describe PgEngine::PgRailsHelper do
|
4
|
+
describe '#img_placeholder' do
|
5
|
+
it 'si no es fade_in' do
|
6
|
+
asd = img_placeholder('bla', fade_in: false, class: 'img-fluid', style: 'color:red')
|
7
|
+
expectation = <<~HTML
|
8
|
+
<img class="img-fluid" style="color:red" src="/images/bla" />
|
9
|
+
HTML
|
10
|
+
expect(asd).to eq expectation.split("\n").map(&:strip).join
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'si tiene style' do
|
14
|
+
asd = img_placeholder('bla', fade_in: true, class: 'img-fluid', style: 'color:red')
|
15
|
+
expectation = <<~HTML
|
16
|
+
<div class="placeholder-glow">
|
17
|
+
<div class="placeholder" style="width: 100%; height: 100%">
|
18
|
+
<img data-controller="fadein_onload" class="img-fluid" style="color:red;display:none" src="/images/bla" />
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
HTML
|
22
|
+
expect(asd).to eq expectation.split("\n").map(&:strip).join
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'si no tiene style' do
|
26
|
+
asd = img_placeholder('bla', fade_in: true, class: 'img-fluid')
|
27
|
+
expectation = <<~HTML
|
28
|
+
<div class="placeholder-glow">
|
29
|
+
<div class="placeholder" style="width: 100%; height: 100%">
|
30
|
+
<img data-controller="fadein_onload" class="img-fluid" style="display:none" src="/images/bla" />
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
HTML
|
34
|
+
expect(asd).to eq expectation.split("\n").map(&:strip).join
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
# rubocop:enable RSpec/ExampleLength
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
TYPES = %i[error warn info].freeze
|
4
|
+
|
5
|
+
describe PgEngine::PgLogger do
|
6
|
+
describe '#pg_warn' do
|
7
|
+
before do
|
8
|
+
TYPES.each do |type|
|
9
|
+
allow(Rails.logger).to receive(type)
|
10
|
+
allow(Rollbar).to receive(type)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
shared_examples 'logger' do |type|
|
15
|
+
it do
|
16
|
+
expect(Rails.logger).to have_received(type).twice
|
17
|
+
end
|
18
|
+
|
19
|
+
it do
|
20
|
+
expect(Rollbar).to have_received(type).once
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
TYPES.each do |type|
|
25
|
+
context "con type #{type}" do
|
26
|
+
before { pg_warn('bla', type) }
|
27
|
+
|
28
|
+
it_behaves_like 'logger', type
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'con exception' do
|
33
|
+
before { pg_warn(StandardError.new('bla')) }
|
34
|
+
|
35
|
+
it_behaves_like 'logger', :error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -10,4 +10,43 @@ RSpec.describe User do
|
|
10
10
|
it 'se persiste' do
|
11
11
|
expect(user).to be_persisted
|
12
12
|
end
|
13
|
+
|
14
|
+
it do
|
15
|
+
expect(user.current_account).to be_present
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'si es orphan' do
|
19
|
+
let(:user) { create(:user, orphan: true) }
|
20
|
+
|
21
|
+
it do
|
22
|
+
expect(user.accounts).to be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
it do
|
26
|
+
expect { user.current_account }.to raise_error(User::Error)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'Si falla la creación de cuenta, que rollbackee la transaction de create user' do
|
31
|
+
let(:user) do
|
32
|
+
build(:user)
|
33
|
+
end
|
34
|
+
|
35
|
+
before do
|
36
|
+
# rubocop:disable RSpec/MessageChain
|
37
|
+
allow(user).to receive_message_chain(:user_accounts, :create) {
|
38
|
+
instance_double(UserAccount, persisted?: false)
|
39
|
+
}
|
40
|
+
# rubocop:enable RSpec/MessageChain
|
41
|
+
end
|
42
|
+
|
43
|
+
it do
|
44
|
+
expect { user.save }.not_to change(described_class, :count)
|
45
|
+
end
|
46
|
+
|
47
|
+
it do
|
48
|
+
user.save
|
49
|
+
expect(user).not_to be_persisted
|
50
|
+
end
|
51
|
+
end
|
13
52
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
// Animations
|
2
|
+
.fade-in {
|
3
|
+
animation: fadeInAnimation 0.2s ease-in-out forwards;
|
4
|
+
}
|
5
|
+
|
6
|
+
.fade-out {
|
7
|
+
animation: fadeOutAnimation 0.2s ease forwards;
|
8
|
+
}
|
9
|
+
|
10
|
+
.init-invisible {
|
11
|
+
visibility: hidden;
|
12
|
+
}
|
13
|
+
|
14
|
+
.animation-long {
|
15
|
+
animation-duration: 1s;
|
16
|
+
}
|
17
|
+
|
18
|
+
@keyframes fadeInAnimation {
|
19
|
+
0% { opacity: 0; visibility: visible; }
|
20
|
+
100% { opacity: 1; visibility: visible; }
|
21
|
+
}
|
22
|
+
|
23
|
+
@keyframes fadeOutAnimation {
|
24
|
+
0% { opacity: 1; visibility: visible; }
|
25
|
+
100% { opacity: 0; visibility: hidden; }
|
26
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
2
|
+
|
3
|
+
// To be used by img_placeholder helper
|
4
|
+
export default class extends Controller {
|
5
|
+
connect () {
|
6
|
+
if (this.element.complete) {
|
7
|
+
this.loaded()
|
8
|
+
} else {
|
9
|
+
this.element.addEventListener('load', () => {
|
10
|
+
this.loaded()
|
11
|
+
}, { once: true })
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
loaded () {
|
16
|
+
this.element.classList.add('fade-in')
|
17
|
+
this.element.style.display = 'block'
|
18
|
+
this.element.parentElement.classList.remove('placeholder')
|
19
|
+
}
|
20
|
+
}
|
@@ -17,3 +17,27 @@ export function showPercentage (value) {
|
|
17
17
|
export function numberWithDots (x) {
|
18
18
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.')
|
19
19
|
}
|
20
|
+
|
21
|
+
export function fadeOut (e) {
|
22
|
+
if (window.getComputedStyle(e).visibility !== 'hidden') {
|
23
|
+
e.classList.add('fade-out')
|
24
|
+
e.addEventListener('animationend', onAnimationEndHide, { once: true })
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
export function fadeIn (e) {
|
29
|
+
if (window.getComputedStyle(e).visibility !== 'visible') {
|
30
|
+
e.classList.add('fade-in')
|
31
|
+
e.addEventListener('animationend', onAnimationEndShow, { once: true })
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
function onAnimationEndShow (e) {
|
36
|
+
e.target.style.visibility = 'visible'
|
37
|
+
e.target.classList.remove('fade-in')
|
38
|
+
}
|
39
|
+
|
40
|
+
function onAnimationEndHide (e) {
|
41
|
+
e.target.style.visibility = 'hidden'
|
42
|
+
e.target.classList.remove('fade-out')
|
43
|
+
}
|
@@ -13,6 +13,7 @@ html
|
|
13
13
|
|
14
14
|
= stylesheet_link_tag 'application', 'data-turbo-track': 'reload'
|
15
15
|
= javascript_include_tag 'application', 'data-turbo-track': 'reload', type: 'module'
|
16
|
+
= render partial: 'pg_layout/rollbar'
|
16
17
|
body
|
17
18
|
div class="#{ @sidebar == false ? '' : 'with-sidebar' }"
|
18
19
|
- unless @sidebar == false
|
@@ -33,4 +34,5 @@ html
|
|
33
34
|
= yield(:actions)
|
34
35
|
hr.my-0
|
35
36
|
= yield
|
37
|
+
div style="width:100%; height: 10em"
|
36
38
|
= render_turbo_stream_title
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% if ENV['ROLLBAR_ACCESS_TOKEN_CLIENT'].present? %>
|
2
|
+
<script>
|
3
|
+
var _rollbarConfig = {
|
4
|
+
accessToken: '<%= ENV['ROLLBAR_ACCESS_TOKEN_CLIENT'] %>',
|
5
|
+
captureUncaught: true,
|
6
|
+
captureUnhandledRejections: true,
|
7
|
+
payload: {
|
8
|
+
environment: "production",
|
9
|
+
//trace_id: 'abc',
|
10
|
+
client: {
|
11
|
+
javascript: {
|
12
|
+
code_version: '1.0.0',
|
13
|
+
//source_map_enabled: true,
|
14
|
+
//guess_uncaught_frames: true
|
15
|
+
}
|
16
|
+
},
|
17
|
+
//server: {
|
18
|
+
//root: 'http://localhost:8000/demo/',
|
19
|
+
//host: 'host-1',
|
20
|
+
//branch: 'HEAD',
|
21
|
+
//},
|
22
|
+
}
|
23
|
+
};
|
24
|
+
// Rollbar Snippet
|
25
|
+
!function(r){var e={};function o(n){if(e[n])return e[n].exports;var t=e[n]={i:n,l:!1,exports:{}};return r[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.m=r,o.c=e,o.d=function(r,e,n){o.o(r,e)||Object.defineProperty(r,e,{enumerable:!0,get:n})},o.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},o.t=function(r,e){if(1&e&&(r=o(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var t in r)o.d(n,t,function(e){return r[e]}.bind(null,t));return n},o.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return o.d(e,"a",e),e},o.o=function(r,e){return Object.prototype.hasOwnProperty.call(r,e)},o.p="",o(o.s=0)}([function(r,e,o){"use strict";var n=o(1),t=o(5);_rollbarConfig=_rollbarConfig||{},_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://cdn.rollbar.com/rollbarjs/refs/tags/v2.26.3/rollbar.min.js",_rollbarConfig.async=void 0===_rollbarConfig.async||_rollbarConfig.async;var a=n.setupShim(window,_rollbarConfig),l=t(_rollbarConfig);window.rollbar=n.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,e,o){"use strict";var n=o(2),t=o(3);function a(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error("[Rollbar]: Internal error",r)}catch(r){}}}}var l=0;function i(r,e){this.options=r,this._rollbarOldOnError=null;var o=l++;this.shimId=function(){return o},"undefined"!=typeof window&&window._rollbarShims&&(window._rollbarShims[o]={handler:e,messages:[]})}var s=o(4),d=function(r,e){return new i(r,e)},c=function(r){return new s(d,r)};function u(r){return a((function(){var e=this,o=Array.prototype.slice.call(arguments,0),n={shim:e,method:r,args:o,ts:new Date};window._rollbarShims[this.shimId()].messages.push(n)}))}i.prototype.loadFull=function(r,e,o,n,t){var l=!1,i=e.createElement("script"),s=e.getElementsByTagName("script")[0],d=s.parentNode;i.crossOrigin="",i.src=n.rollbarJsUrl,o||(i.async=!0),i.onload=i.onreadystatechange=a((function(){if(!(l||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){i.onload=i.onreadystatechange=null;try{d.removeChild(i)}catch(r){}l=!0,function(){var e;if(void 0===r._rollbarDidLoad){e=new Error("rollbar.js did not load");for(var o,n,a,l,i=0;o=r._rollbarShims[i++];)for(o=o.messages||[];n=o.shift();)for(a=n.args||[],i=0;i<a.length;++i)if("function"==typeof(l=a[i])){l(e);break}}"function"==typeof t&&t(e)}()}})),d.insertBefore(i,s)},i.prototype.wrap=function(r,e,o){try{var n;if(n="function"==typeof e?e:function(){return e||{}},"function"!=typeof r)return r;if(r._isWrap)return r;if(!r._rollbar_wrapped&&(r._rollbar_wrapped=function(){o&&"function"==typeof o&&o.apply(this,arguments);try{return r.apply(this,arguments)}catch(o){var e=o;throw e&&("string"==typeof e&&(e=new String(e)),e._rollbarContext=n()||{},e._rollbarContext._wrappedSource=r.toString(),window._rollbarWrappedError=e),e}},r._rollbar_wrapped._isWrap=!0,r.hasOwnProperty))for(var t in r)r.hasOwnProperty(t)&&(r._rollbar_wrapped[t]=r[t]);return r._rollbar_wrapped}catch(e){return r}};for(var p="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,captureEvent,captureDomContentLoaded,captureLoad".split(","),f=0;f<p.length;++f)i.prototype[p[f]]=u(p[f]);r.exports={setupShim:function(r,e){if(r){var o=e.globalAlias||"Rollbar";if("object"==typeof r[o])return r[o];r._rollbarShims={},r._rollbarWrappedError=null;var l=new c(e);return a((function(){e.captureUncaught&&(l._rollbarOldOnError=r.onerror,n.captureUncaughtExceptions(r,l,!0),e.wrapGlobalEventHandlers&&t(r,l,!0)),e.captureUnhandledRejections&&n.captureUnhandledRejections(r,l,!0);var a=e.autoInstrument;return!1!==e.enabled&&(void 0===a||!0===a||function(r){return!("object"!=typeof r||void 0!==r.page&&!r.page)}(a))&&r.addEventListener&&(r.addEventListener("load",l.captureLoad.bind(l)),r.addEventListener("DOMContentLoaded",l.captureDomContentLoaded.bind(l))),r[o]=l,l}))()}},Rollbar:c}},function(r,e,o){"use strict";function n(r,e,o,n){r._rollbarWrappedError&&(n[4]||(n[4]=r._rollbarWrappedError),n[5]||(n[5]=r._rollbarWrappedError._rollbarContext),r._rollbarWrappedError=null);var t=e.handleUncaughtException.apply(e,n);o&&o.apply(r,n),"anonymous"===t&&(e.anonymousErrorsPending+=1)}r.exports={captureUncaughtExceptions:function(r,e,o){if(r){var t;if("function"==typeof e._rollbarOldOnError)t=e._rollbarOldOnError;else if(r.onerror){for(t=r.onerror;t._rollbarOldOnError;)t=t._rollbarOldOnError;e._rollbarOldOnError=t}e.handleAnonymousErrors();var a=function(){var o=Array.prototype.slice.call(arguments,0);n(r,e,t,o)};o&&(a._rollbarOldOnError=t),r.onerror=a}},captureUnhandledRejections:function(r,e,o){if(r){"function"==typeof r._rollbarURH&&r._rollbarURH.belongsToShim&&r.removeEventListener("unhandledrejection",r._rollbarURH);var n=function(r){var o,n,t;try{o=r.reason}catch(r){o=void 0}try{n=r.promise}catch(r){n="[unhandledrejection] error getting `promise` from event"}try{t=r.detail,!o&&t&&(o=t.reason,n=t.promise)}catch(r){}o||(o="[unhandledrejection] error getting `reason` from event"),e&&e.handleUnhandledRejection&&e.handleUnhandledRejection(o,n)};n.belongsToShim=o,r._rollbarURH=n,r.addEventListener("unhandledrejection",n)}}}},function(r,e,o){"use strict";function n(r,e,o){if(e.hasOwnProperty&&e.hasOwnProperty("addEventListener")){for(var n=e.addEventListener;n._rollbarOldAdd&&n.belongsToShim;)n=n._rollbarOldAdd;var t=function(e,o,t){n.call(this,e,r.wrap(o),t)};t._rollbarOldAdd=n,t.belongsToShim=o,e.addEventListener=t;for(var a=e.removeEventListener;a._rollbarOldRemove&&a.belongsToShim;)a=a._rollbarOldRemove;var l=function(r,e,o){a.call(this,r,e&&e._rollbar_wrapped||e,o)};l._rollbarOldRemove=a,l.belongsToShim=o,e.removeEventListener=l}}r.exports=function(r,e,o){if(r){var t,a,l="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(t=0;t<l.length;++t)r[a=l[t]]&&r[a].prototype&&n(e,r[a].prototype,o)}}},function(r,e,o){"use strict";function n(r,e){this.impl=r(e,this),this.options=e,function(r){for(var e=function(r){return function(){var e=Array.prototype.slice.call(arguments,0);if(this.impl[r])return this.impl[r].apply(this.impl,e)}},o="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureEvent,captureDomContentLoaded,captureLoad".split(","),n=0;n<o.length;n++)r[o[n]]=e(o[n])}(n.prototype)}n.prototype._swapAndProcessMessages=function(r,e){var o,n,t;for(this.impl=r(this.options);o=e.shift();)n=o.method,t=o.args,this[n]&&"function"==typeof this[n]&&("captureDomContentLoaded"===n||"captureLoad"===n?this[n].apply(this,[t[0],o.ts]):this[n].apply(this,t));return this},r.exports=n},function(r,e,o){"use strict";r.exports=function(r){return function(e){if(!e&&!window._rollbarInitialized){for(var o,n,t=(r=r||{}).globalAlias||"Rollbar",a=window.rollbar,l=function(r){return new a(r)},i=0;o=window._rollbarShims[i++];)n||(n=o.handler),o.handler._swapAndProcessMessages(l,o.messages);window[t]=n,window._rollbarInitialized=!0}}}}]);
|
26
|
+
// End Rollbar Snippet
|
27
|
+
</script>
|
28
|
+
<% end %>
|
data/pg_layout/index.js
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
import NavbarController from './app/javascript/navbar_controller'
|
3
3
|
import NestedController from './app/javascript/nested_controller'
|
4
4
|
import PgFormController from './app/javascript/pg_form_controller'
|
5
|
+
import FadeinOnloadController from './app/javascript/fadein_onload_controller'
|
5
6
|
// Bootstrap's toasts
|
6
7
|
import * as bootstrap from 'bootstrap'
|
7
8
|
|
8
9
|
window.Stimulus.register('navbar', NavbarController)
|
9
10
|
window.Stimulus.register('nested', NestedController)
|
10
11
|
window.Stimulus.register('pg_form', PgFormController)
|
12
|
+
window.Stimulus.register('fadein_onload', FadeinOnloadController)
|
11
13
|
|
12
14
|
document.addEventListener('turbo:load', function () {
|
13
15
|
const toastElList = document.querySelectorAll('.toast:not(.hide):not(.show)')
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'vcr'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
|
4
|
+
VCR.configure do |config|
|
5
|
+
config.cassette_library_dir = 'spec/cassettes'
|
6
|
+
config.default_cassette_options = {
|
7
|
+
match_requests_on: %i[uri method],
|
8
|
+
record: :once
|
9
|
+
}
|
10
|
+
config.hook_into :webmock
|
11
|
+
config.configure_rspec_metadata!
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.around(:example, :vcr_cassettes) do |example|
|
16
|
+
cassettes = example.metadata[:vcr_cassettes].map { |cas_name| { name: cas_name } }
|
17
|
+
VCR.use_cassettes(cassettes) do
|
18
|
+
example.run
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/pg_rails/lib/version.rb
CHANGED
data/pg_rails/scss/pg_rails.scss
CHANGED
@@ -9,6 +9,8 @@ require_dependency "<%= namespaced_path %>/application_controller"
|
|
9
9
|
<% module_namespacing do -%>
|
10
10
|
<% module_namespacing_2 do -%>
|
11
11
|
class <%= controller_class_name.split('::').last %>Controller < <%= parent_controller %>
|
12
|
+
include PgEngine::Resource
|
13
|
+
|
12
14
|
before_action { @clase_modelo = <%= class_name.split('::').last %> }
|
13
15
|
|
14
16
|
before_action(only: :index) { authorize <%= class_name.split('::').last %> }
|
@@ -6,7 +6,7 @@ require 'generators/pg_active_record/model/model_generator'
|
|
6
6
|
|
7
7
|
DESTINATION_PATH = File.expand_path('./../../tmp/generator_testing', __dir__)
|
8
8
|
|
9
|
-
describe 'Generators' do
|
9
|
+
describe 'Generators', type: :generator do
|
10
10
|
describe 'PgDecoratorGenerator' do
|
11
11
|
destination DESTINATION_PATH
|
12
12
|
tests PgDecoratorGenerator
|
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.0.8.pre.alpha.
|
4
|
+
version: 7.0.8.pre.alpha.14
|
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-03-
|
11
|
+
date: 2024-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Rails goodies.
|
14
14
|
email:
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- pg_engine/app/views/pg_engine/base/new.html.slim
|
91
91
|
- pg_engine/config/initializers/active_admin.rb
|
92
92
|
- pg_engine/config/initializers/devise.rb
|
93
|
+
- pg_engine/config/initializers/rollbar.rb
|
93
94
|
- pg_engine/config/initializers/simple_form_monkey_patch.rb
|
94
95
|
- pg_engine/config/locales/devise.en.yml
|
95
96
|
- pg_engine/config/locales/es.yml
|
@@ -117,21 +118,26 @@ files:
|
|
117
118
|
- pg_engine/spec/controllers/admin/accounts_controller_spec.rb
|
118
119
|
- pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb
|
119
120
|
- pg_engine/spec/controllers/admin/users_controller_spec.rb
|
120
|
-
- pg_engine/spec/controllers/concerns/pg_engine/
|
121
|
+
- pg_engine/spec/controllers/concerns/pg_engine/resource_helper_spec.rb
|
121
122
|
- pg_engine/spec/controllers/devise/registrations_controller_spec.rb
|
122
123
|
- pg_engine/spec/controllers/devise/sessions_controller_spec.rb
|
123
124
|
- pg_engine/spec/factories/accounts.rb
|
124
125
|
- pg_engine/spec/factories/user_accounts.rb
|
125
126
|
- pg_engine/spec/factories/users.rb
|
126
127
|
- pg_engine/spec/fixtures/test.pdf
|
128
|
+
- pg_engine/spec/helpers/pg_engine/pg_rails_helper_spec.rb
|
129
|
+
- pg_engine/spec/lib/pg_engine/error_helper_spec.rb
|
130
|
+
- pg_engine/spec/lib/pg_engine/utils/pg_engine/pg_logger_spec.rb
|
127
131
|
- pg_engine/spec/lib/pg_form_builder_spec.rb
|
128
132
|
- pg_engine/spec/models/account_spec.rb
|
129
133
|
- pg_engine/spec/models/pg_engine/base_record_spec.rb
|
130
134
|
- pg_engine/spec/models/user_account_spec.rb
|
131
135
|
- pg_engine/spec/models/user_spec.rb
|
132
136
|
- pg_engine/spec/pg_engine/pdf_preview_generator_spec.rb
|
137
|
+
- pg_layout/app/assets/stylesheets/animations.scss
|
133
138
|
- pg_layout/app/assets/stylesheets/sidebar.scss
|
134
139
|
- pg_layout/app/javascript/cookies.js
|
140
|
+
- pg_layout/app/javascript/fadein_onload_controller.js
|
135
141
|
- pg_layout/app/javascript/navbar_controller.js
|
136
142
|
- pg_layout/app/javascript/nested_controller.js
|
137
143
|
- pg_layout/app/javascript/pg_form_controller.js
|
@@ -162,6 +168,7 @@ files:
|
|
162
168
|
- pg_layout/app/views/layouts/pg_layout/layout.html.slim
|
163
169
|
- pg_layout/app/views/pg_layout/_flash.html.slim
|
164
170
|
- pg_layout/app/views/pg_layout/_navbar.html.erb
|
171
|
+
- pg_layout/app/views/pg_layout/_rollbar.html.erb
|
165
172
|
- pg_layout/app/views/pg_layout/_sidebar.html.erb
|
166
173
|
- pg_layout/index.js
|
167
174
|
- pg_layout/lib/pg_layout.rb
|
@@ -169,6 +176,7 @@ files:
|
|
169
176
|
- pg_rails/js/index.js
|
170
177
|
- pg_rails/lib/pg_rails.rb
|
171
178
|
- pg_rails/lib/pg_rails/capybara_support.rb
|
179
|
+
- pg_rails/lib/pg_rails/vcr_support.rb
|
172
180
|
- pg_rails/lib/version.rb
|
173
181
|
- pg_rails/scss/pg_rails.scss
|
174
182
|
- pg_scaffold/lib/generators/pg_active_record/model/model_generator.rb
|
File without changes
|