pg_rails 7.6.20 → 7.6.21.pre.2
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_associable/app/javascript/modal_controller.js +8 -4
- data/pg_associable/spec/pg_associable/helpers_spec.rb +8 -13
- data/pg_engine/app/components/inline_edit/inline_edit_component.html.slim +1 -1
- data/pg_engine/app/components/inline_edit/inline_show_component.html.slim +2 -2
- data/pg_engine/app/components/notifications_bell_component.rb +1 -1
- data/pg_engine/app/controllers/admin/accounts_controller.rb +2 -2
- data/pg_engine/app/controllers/admin/user_accounts_controller.rb +3 -3
- data/pg_engine/app/controllers/admin/users_controller.rb +4 -1
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +12 -7
- data/pg_engine/app/controllers/concerns/pg_engine/tenant_helper.rb +33 -0
- data/pg_engine/app/controllers/pg_engine/base_admin_controller.rb +0 -1
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +18 -21
- data/pg_engine/app/controllers/pg_engine/base_public_controller.rb +1 -1
- data/pg_engine/app/controllers/pg_engine/base_users_controller.rb +5 -3
- data/pg_engine/app/controllers/pg_engine/devise_controller.rb +4 -1
- data/pg_engine/app/controllers/pg_engine/tenant_controller.rb +22 -0
- data/pg_engine/app/controllers/{users → tenant}/dashboard_controller.rb +2 -2
- data/pg_engine/app/controllers/tenant/inline_edit_controller.rb +22 -0
- data/pg_engine/app/controllers/tenant/user_accounts_controller.rb +56 -0
- data/pg_engine/app/controllers/users/accounts_controller.rb +46 -15
- data/pg_engine/app/controllers/users/invitations_controller.rb +78 -0
- data/pg_engine/app/controllers/users/notifications_controller.rb +1 -0
- data/pg_engine/app/controllers/users/registrations_controller.rb +3 -2
- data/pg_engine/app/decorators/account_decorator.rb +18 -0
- data/pg_engine/app/decorators/pg_engine/base_record_decorator.rb +9 -1
- data/pg_engine/app/decorators/user_account_decorator.rb +76 -11
- data/pg_engine/app/helpers/pg_engine/accounts_helper.rb +9 -0
- data/pg_engine/app/helpers/pg_engine/frame_helper.rb +12 -0
- data/pg_engine/app/lib/pg_engine/default_url_options.rb +21 -0
- data/pg_engine/app/lib/pg_engine/filtros_builder.rb +2 -0
- data/pg_engine/app/models/account.rb +28 -1
- data/pg_engine/app/models/concerns/pg_engine/child_record.rb +55 -0
- data/pg_engine/app/models/current.rb +29 -3
- data/pg_engine/app/models/pg_engine/base_record.rb +5 -0
- data/pg_engine/app/models/user.rb +56 -14
- data/pg_engine/app/models/user_account.rb +74 -9
- data/pg_engine/app/policies/account_policy.rb +35 -16
- data/pg_engine/app/policies/email_log_policy.rb +0 -4
- data/pg_engine/app/policies/email_policy.rb +0 -4
- data/pg_engine/app/policies/pg_engine/base_policy.rb +31 -10
- data/pg_engine/app/policies/user_account_policy.rb +59 -25
- data/pg_engine/app/policies/user_policy.rb +14 -1
- data/pg_engine/app/views/admin/user_accounts/_form.html.slim +1 -1
- data/pg_engine/app/views/admin/user_accounts/show.html.slim +15 -0
- data/pg_engine/app/views/admin/users/show.html.slim +0 -3
- data/pg_engine/app/views/pg_engine/base/index.html.slim +2 -2
- data/pg_engine/app/views/tenant/dashboard/dashboard.html.slim +2 -0
- data/pg_engine/app/views/tenant/user_accounts/_fields.html.slim +13 -0
- data/pg_engine/app/views/tenant/user_accounts/_form.html.slim +9 -0
- data/pg_engine/app/views/tenant/user_accounts/show.html.slim +20 -0
- data/pg_engine/app/views/users/accounts/_form.html.slim +7 -0
- data/pg_engine/app/views/users/accounts/show.html.slim +23 -15
- data/pg_engine/config/initializers/acts_as_tenant.rb +7 -2
- data/pg_engine/config/initializers/devise.rb +10 -0
- data/pg_engine/config/initializers/ransack.rb +2 -0
- data/pg_engine/config/locales/es.yml +60 -0
- data/pg_engine/config/routes.rb +21 -11
- data/pg_engine/config/simple_form/simple_form_bootstrap.rb +2 -2
- data/pg_engine/db/migrate/20241023203849_devise_invitable.rb +14 -0
- data/pg_engine/db/migrate/20241027225618_add_membership_status_to_user_accounts.rb +6 -0
- data/pg_engine/db/seeds.rb +6 -6
- data/pg_engine/lib/pg_engine/configuracion.rb +36 -1
- data/pg_engine/lib/pg_engine/navigator.rb +2 -25
- data/pg_engine/lib/pg_engine.rb +1 -0
- data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +3 -2
- data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +11 -9
- data/pg_engine/spec/factories/accounts.rb +8 -0
- data/pg_engine/spec/factories/user_accounts.rb +1 -1
- data/pg_engine/spec/factories/users.rb +6 -0
- data/pg_engine/spec/models/concerns/pg_engine/child_record_spec.rb +27 -0
- data/pg_engine/spec/models/user_account_spec.rb +5 -1
- data/pg_engine/spec/models/user_spec.rb +3 -25
- data/pg_engine/spec/policies/account_policy_spec.rb +19 -0
- data/pg_engine/spec/requests/devise/invitations_spec.rb +196 -0
- data/pg_engine/spec/requests/resource_spec.rb +14 -15
- data/pg_engine/spec/requests/users/accounts_spec.rb +117 -8
- data/pg_engine/spec/requests/users/base_controller_spec.rb +31 -0
- data/pg_engine/spec/requests/users/dashboard_spec.rb +4 -9
- data/pg_engine/spec/requests/users/date_jumper_spec.rb +2 -1
- data/pg_engine/spec/requests/users/inline_edit_spec.rb +6 -5
- data/pg_engine/spec/requests/users/registrations_spec.rb +2 -2
- data/pg_engine/spec/requests/users/user_accounts_spec.rb +54 -0
- data/pg_engine/spec/system/login_spec.rb +2 -2
- data/pg_engine/spec/system/noticed_spec.rb +0 -2
- data/pg_engine/spec/system/signup_spec.rb +4 -3
- data/pg_engine/spec/system/tenants_spec.rb +10 -9
- data/pg_layout/app/javascript/application.js +1 -1
- data/pg_layout/app/javascript/config/turbo_rails/index.js +1 -1
- data/pg_layout/app/lib/navbar.rb +15 -1
- data/pg_layout/app/views/devise/invitations/edit.html.erb +34 -0
- data/pg_layout/app/views/devise/invitations/new.html.erb +15 -0
- data/pg_layout/app/views/devise/mailer/invitation_instructions.html.erb +11 -0
- data/pg_layout/app/views/devise/mailer/invitation_instructions.text.erb +11 -0
- data/pg_layout/app/views/devise/registrations/edit.html.erb +1 -0
- data/pg_layout/app/views/layouts/pg_layout/base.html.slim +7 -5
- data/pg_layout/app/views/pg_layout/_navbar.html.erb +7 -6
- data/pg_layout/app/views/pg_layout/_sidebar.html.erb +2 -20
- data/pg_layout/app/views/pg_layout/_signed_in_links.html.slim +52 -0
- data/pg_layout/lib/pg_layout.rb +0 -5
- data/pg_rails/lib/pg_rails/pundit_matchers.rb +21 -0
- data/pg_rails/lib/pg_rails/tpath_support.rb +73 -0
- data/pg_rails/lib/pg_rails.rb +6 -0
- data/pg_rails/lib/version.rb +1 -1
- data/pg_rails/scss/pg_rails.scss +1 -1
- data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +1 -1
- data/pg_scaffold/lib/generators/pg_slim/templates/index.html.slim +1 -1
- metadata +43 -9
- data/pg_engine/app/controllers/concerns/pg_engine/require_tenant_set.rb +0 -15
- data/pg_engine/app/controllers/users/account_switcher_controller.rb +0 -30
- data/pg_engine/app/controllers/users/inline_edit_controller.rb +0 -21
- data/pg_engine/app/views/users/account_switcher/list.html.slim +0 -24
- data/pg_engine/app/views/users/dashboard/dashboard.html.slim +0 -1
- data/pg_engine/spec/requests/users/switcher_spec.rb +0 -84
|
@@ -2,20 +2,129 @@ require 'rails_helper'
|
|
|
2
2
|
|
|
3
3
|
describe 'Users::AccountsController' do
|
|
4
4
|
let(:account) { ActsAsTenant.current_tenant }
|
|
5
|
-
let(:user) { create :user }
|
|
5
|
+
let(:user) { create :user, :owner }
|
|
6
6
|
|
|
7
7
|
before do
|
|
8
8
|
sign_in user
|
|
9
|
+
create_list :user, 2
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
describe 'show' do
|
|
13
|
+
it 'shows the owned account' do
|
|
14
|
+
get "/u/espacios/#{account.to_param}"
|
|
15
|
+
expect(response).to have_http_status(:ok)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'denies foreign account' do
|
|
19
|
+
other_account = create :account
|
|
20
|
+
get "/u/espacios/#{other_account.to_param}"
|
|
21
|
+
expect(response).to have_http_status(:unauthorized)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'when not the owner' do
|
|
25
|
+
subject do
|
|
26
|
+
get "/u/espacios/#{other_account.to_param}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let(:other_account) { create :account }
|
|
30
|
+
let(:membership_status) { :ms_active }
|
|
31
|
+
let(:invitation_status) { :ist_accepted }
|
|
32
|
+
let(:profiles) { [] }
|
|
33
|
+
|
|
34
|
+
before do
|
|
35
|
+
ActsAsTenant.with_tenant(other_account) do
|
|
36
|
+
create :user, :owner
|
|
37
|
+
create :user_account, user:, invitation_status:, membership_status:, profiles:
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'when its active' do
|
|
42
|
+
let(:profiles) { [:user_accounts__read] }
|
|
43
|
+
|
|
44
|
+
pending 'See the users'
|
|
45
|
+
|
|
46
|
+
it do
|
|
47
|
+
subject
|
|
48
|
+
# expect(response.body).to have_text('Lista de usuarios')
|
|
49
|
+
expect(response.body).to have_text('Dejar la cuenta')
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'when its active and dont have user_accounts__read access' do
|
|
54
|
+
it do
|
|
55
|
+
subject
|
|
56
|
+
expect(response.body).to have_no_text('Lista de usuarios')
|
|
57
|
+
expect(response.body).to have_text('Dejar la cuenta')
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context 'when its disabled' do
|
|
62
|
+
let(:membership_status) { :ms_disabled }
|
|
63
|
+
|
|
64
|
+
it do
|
|
65
|
+
subject
|
|
66
|
+
expect(response.body).to have_text('Deshabilitado')
|
|
67
|
+
expect(response.body).to have_text('Dejar la cuenta')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context 'when its invited' do
|
|
72
|
+
let(:invitation_status) { :ist_invited }
|
|
73
|
+
|
|
74
|
+
it do
|
|
75
|
+
subject
|
|
76
|
+
expect(response).to have_http_status(:unauthorized)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe 'index' do
|
|
83
|
+
subject do
|
|
84
|
+
get '/u/espacios'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
before do
|
|
88
|
+
other_account = create :account, :with_owner
|
|
89
|
+
ActsAsTenant.without_tenant do
|
|
90
|
+
create :user_account, account: other_account, user:, invitation_status:, membership_status:
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'cuando está invitado' do
|
|
95
|
+
let(:invitation_status) { :ist_invited }
|
|
96
|
+
let(:membership_status) { :ms_active }
|
|
97
|
+
|
|
98
|
+
it do
|
|
99
|
+
subject
|
|
100
|
+
expect(response.body).to have_text('Aceptar invitación')
|
|
101
|
+
expect(response.body).to have_text('Rechazar')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context 'y deshabilitado' do
|
|
105
|
+
let(:membership_status) { :ms_disabled }
|
|
106
|
+
|
|
107
|
+
it do
|
|
108
|
+
subject
|
|
109
|
+
expect(response.body).to have_no_text('Aceptar invitación')
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
14
113
|
end
|
|
15
114
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
115
|
+
describe 'create an account' do
|
|
116
|
+
subject do
|
|
117
|
+
post '/u/espacios', params: {
|
|
118
|
+
account: {
|
|
119
|
+
plan: :completar,
|
|
120
|
+
nombre: Faker::Lorem.sentence
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it do
|
|
126
|
+
expect { subject }.to change(Account, :count).by(1)
|
|
127
|
+
expect(Account.last.owner).to eq user
|
|
128
|
+
end
|
|
20
129
|
end
|
|
21
130
|
end
|
|
@@ -12,4 +12,35 @@ describe 'redirection' do
|
|
|
12
12
|
expect(response).to have_http_status(:internal_server_error)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
|
+
|
|
16
|
+
context 'when logged in', :tpath_req do
|
|
17
|
+
let(:logged_user) { create :user, :owner }
|
|
18
|
+
|
|
19
|
+
before do
|
|
20
|
+
sign_in logged_user
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'when account is discarded' do
|
|
24
|
+
it do
|
|
25
|
+
get '/u/t/cosas'
|
|
26
|
+
expect(response.body).to include 'No hay ningún coso que mostrar'
|
|
27
|
+
logged_user.user_accounts.first.account.discard!
|
|
28
|
+
get '/u/t/cosas'
|
|
29
|
+
expect(response).to redirect_to users_accounts_path, tpath: false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'when belongs to other account', pending: 'subdomains not ready' do
|
|
34
|
+
before do
|
|
35
|
+
create :account, subdomain: 'other'
|
|
36
|
+
host! 'other.example.com'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it do
|
|
40
|
+
get '/u/t/cosas'
|
|
41
|
+
|
|
42
|
+
expect(response).to redirect_to new_user_session_path, tpath: false
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
15
46
|
end
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
require 'rails_helper'
|
|
2
2
|
|
|
3
|
-
describe 'DASHBOARD' do
|
|
4
|
-
let(:logged_user) { create :user }
|
|
3
|
+
describe 'DASHBOARD', :tpath_req do
|
|
4
|
+
let(:logged_user) { create :user, :owner }
|
|
5
5
|
|
|
6
6
|
before do
|
|
7
7
|
sign_in logged_user
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
it 'when requesting /u' do
|
|
11
|
-
get '/u'
|
|
12
|
-
expect(response.body).to include '<h1>Dashboard</h1>'
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it 'when requesting /u/dashboard' do
|
|
16
|
-
get '/u/dashboard'
|
|
10
|
+
it 'when requesting /u/t/dashboard' do
|
|
11
|
+
get '/u/t/dashboard'
|
|
17
12
|
expect(response.body).to include '<h1>Dashboard</h1>'
|
|
18
13
|
end
|
|
19
14
|
end
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
require 'rails_helper'
|
|
2
2
|
|
|
3
|
-
describe 'inline edit' do
|
|
3
|
+
describe 'inline edit', :tpath_req do
|
|
4
4
|
before do
|
|
5
|
-
user = create :user
|
|
6
5
|
sign_in user
|
|
7
6
|
end
|
|
8
7
|
|
|
8
|
+
let(:user) { create :user, :owner }
|
|
9
|
+
|
|
9
10
|
let(:cosa) { create :cosa }
|
|
10
11
|
|
|
11
12
|
describe '#show' do
|
|
12
13
|
subject do
|
|
13
|
-
get '/u/inline/show', params:, headers: { 'Turbo-Frame': turbo_frame_id }
|
|
14
|
+
get '/u/t/inline/show', params:, headers: { 'Turbo-Frame': turbo_frame_id }
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
let(:params) do
|
|
@@ -37,7 +38,7 @@ describe 'inline edit' do
|
|
|
37
38
|
|
|
38
39
|
describe '#edit' do
|
|
39
40
|
subject do
|
|
40
|
-
get '/u/inline/edit', params:, headers: { 'Turbo-Frame': turbo_frame_id }
|
|
41
|
+
get '/u/t/inline/edit', params:, headers: { 'Turbo-Frame': turbo_frame_id }
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
let(:params) do
|
|
@@ -64,7 +65,7 @@ describe 'inline edit' do
|
|
|
64
65
|
|
|
65
66
|
describe '#update' do
|
|
66
67
|
subject do
|
|
67
|
-
patch "/u/cosas/#{cosa.to_param}", params:
|
|
68
|
+
patch "/u/t/cosas/#{cosa.to_param}", params:
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
let(:params) do
|
|
@@ -39,7 +39,7 @@ describe 'registrations controller' do
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it do
|
|
42
|
-
subject
|
|
42
|
+
expect { subject }.to change(User, :count).by(1)
|
|
43
43
|
expect(response.body).to include I18n.t('devise.registrations.signed_up_but_unconfirmed')
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -80,7 +80,7 @@ describe 'registrations controller' do
|
|
|
80
80
|
expect { subject }.to change(User, :count).by(1)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
it do
|
|
83
|
+
it 'creates the user account', pending: 'subdomains not working' do
|
|
84
84
|
expect { subject }.to change(UserAccount, :count).by(1)
|
|
85
85
|
end
|
|
86
86
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
describe 'user accounts', :tpath_req do
|
|
4
|
+
let!(:logged_user) { create :user, :owner }
|
|
5
|
+
|
|
6
|
+
let(:account) { ActsAsTenant.current_tenant }
|
|
7
|
+
let!(:user_account) { create :user_account, account: }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
sign_in logged_user
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
pending 'index'
|
|
14
|
+
|
|
15
|
+
describe 'show' do
|
|
16
|
+
it do
|
|
17
|
+
get "/u/t/user_accounts/#{user_account.to_param}"
|
|
18
|
+
expect(response).to have_http_status(:ok)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'edit' do
|
|
23
|
+
it do
|
|
24
|
+
get "/u/t/user_accounts/#{user_account.to_param}/edit"
|
|
25
|
+
expect(response).to have_http_status(:ok)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe 'update' do
|
|
30
|
+
subject do
|
|
31
|
+
params = {
|
|
32
|
+
user_account: {
|
|
33
|
+
profiles: ['cosas__read']
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
patch "/u/t/user_accounts/#{user_account.to_param}", params:
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it do
|
|
40
|
+
expect { subject }.to(change { user_account.reload.profiles }.to(include('cosas__read')))
|
|
41
|
+
expect(response).to redirect_to([:tenant, user_account])
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe 'destroy' do
|
|
46
|
+
subject do
|
|
47
|
+
delete "/u/t/user_accounts/#{user_account.to_param}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it do
|
|
51
|
+
expect { subject }.to change(UserAccount.unscoped, :count).by(-1)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -5,14 +5,14 @@ require 'rails_helper'
|
|
|
5
5
|
describe 'Sign in' do
|
|
6
6
|
shared_examples 'sign_in' do
|
|
7
7
|
subject do
|
|
8
|
-
visit '/u/categoria_de_cosas'
|
|
8
|
+
visit '/u/t/categoria_de_cosas'
|
|
9
9
|
fill_in 'user_email', with: user.email
|
|
10
10
|
fill_in 'user_password', with: password
|
|
11
11
|
find('input[type=submit]').click
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
let(:password) { 'pass1234' }
|
|
15
|
-
let!(:user) { create :user, password: }
|
|
15
|
+
let!(:user) { create :user, :owner, password: }
|
|
16
16
|
|
|
17
17
|
it do
|
|
18
18
|
subject
|
|
@@ -34,10 +34,11 @@ describe 'Al Registrarse' do
|
|
|
34
34
|
check 'user_accept_terms'
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
pending 'expect new account created also'
|
|
38
|
-
|
|
39
37
|
it 'guarda el user' do
|
|
40
|
-
expect { subject }.to change(User.unscoped, :count).by(1)
|
|
38
|
+
expect { subject }.to change(User.unscoped, :count).by(1).and(change(Account, :count).by(1))
|
|
39
|
+
ActsAsTenant.without_tenant do
|
|
40
|
+
expect(Account.last.owner).to eq User.last
|
|
41
|
+
end
|
|
41
42
|
expect(page).to have_text('Te enviamos un correo electrónico con instrucciones')
|
|
42
43
|
end
|
|
43
44
|
end
|
|
@@ -9,16 +9,16 @@ require 'rails_helper'
|
|
|
9
9
|
# DRIVER=selenium rspec
|
|
10
10
|
describe 'Tenants' do
|
|
11
11
|
subject(:visitar) do
|
|
12
|
-
visit '/u/cosas'
|
|
12
|
+
visit '/u/t/cosas'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
let(:logged_user) { create :user }
|
|
15
|
+
let(:logged_user) { create :user, :owner }
|
|
16
16
|
|
|
17
17
|
before do
|
|
18
18
|
login_as logged_user
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
describe '
|
|
21
|
+
describe 'account management' do
|
|
22
22
|
it do
|
|
23
23
|
visitar
|
|
24
24
|
|
|
@@ -30,21 +30,22 @@ describe 'Tenants' do
|
|
|
30
30
|
|
|
31
31
|
before do
|
|
32
32
|
ActsAsTenant.with_tenant(other_account) do
|
|
33
|
-
logged_user.user_accounts.create!
|
|
33
|
+
logged_user.user_accounts.create!(profiles: [:account__owner])
|
|
34
34
|
end
|
|
35
|
+
driven_by :selenium_chrome_headless_notebook
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
it 'shows the
|
|
38
|
+
it 'shows the accounts index' do
|
|
38
39
|
visitar
|
|
39
40
|
|
|
40
|
-
expect(page).to have_text '
|
|
41
|
+
expect(page).to have_text 'Mostrando un total de 2 espacios'
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
it 'switches to account' do
|
|
44
45
|
visitar
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
find_all('a', text: 'Ingresar').first.click
|
|
47
|
+
# visit '/u/t/categoria_de_cosas'
|
|
48
|
+
click_on 'Categorias front'
|
|
48
49
|
expect(page).to have_text 'No hay ninguna categoría de cosa que mostrar'
|
|
49
50
|
end
|
|
50
51
|
|
|
@@ -67,7 +67,7 @@ document.addEventListener('turbo:before-fetch-request', (ev) => {
|
|
|
67
67
|
// Si es POST, quito la opción text/vnd.turbo-stream.html para que
|
|
68
68
|
// on successful redirect no haya posibilidad de que se abra un modal.
|
|
69
69
|
// Si el link o form tiene data-turbo-stream entonces no se pisa el header.
|
|
70
|
-
//
|
|
70
|
+
// TODO!: buscar una manera mejor de hacerlo porque es para problemas
|
|
71
71
|
// quizás, con la movida de abrir modales desde JS
|
|
72
72
|
if (ev.detail.fetchOptions.method.toLowerCase() === 'post' &&
|
|
73
73
|
ev.target.dataset.turboStream === undefined) {
|
|
@@ -10,7 +10,7 @@ import Rollbar from 'rollbar'
|
|
|
10
10
|
// TODO: testear con capybara
|
|
11
11
|
document.addEventListener('turbo:before-cache', () => {
|
|
12
12
|
document.querySelectorAll('#flash .alert').forEach((el) => {
|
|
13
|
-
//
|
|
13
|
+
// TODO!: en los destroy desde main frame, turbo llama a before-cache
|
|
14
14
|
// después de renderear el redirect, por eso no puedo hacer el remove
|
|
15
15
|
//
|
|
16
16
|
// el.remove()
|
data/pg_layout/app/lib/navbar.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
class Navbar
|
|
2
|
+
include PgEngine::DefaultUrlOptions
|
|
2
3
|
include Rails.application.routes.url_helpers
|
|
3
4
|
|
|
4
5
|
attr_reader :extensiones
|
|
@@ -19,9 +20,22 @@ class Navbar
|
|
|
19
20
|
@yaml_data[key] << ActiveSupport::HashWithIndifferentAccess.new(obj)
|
|
20
21
|
end
|
|
21
22
|
|
|
23
|
+
# Idempotent to be called right before render
|
|
24
|
+
def configure
|
|
25
|
+
return if @configured
|
|
26
|
+
|
|
27
|
+
PgEngine.configuracion.navigators.each do |navigator|
|
|
28
|
+
navigator.configure(self)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@configured = true
|
|
32
|
+
end
|
|
33
|
+
|
|
22
34
|
def sidebar
|
|
35
|
+
configure
|
|
36
|
+
|
|
23
37
|
ret = bar(@user.present? ? 'sidebar.signed_in' : 'sidebar.not_signed_in')
|
|
24
|
-
ret.push(*bar('sidebar.developer')) if
|
|
38
|
+
ret.push(*bar('sidebar.developer')) if Current.namespace == :admin
|
|
25
39
|
ret
|
|
26
40
|
end
|
|
27
41
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<h2><%#= t "devise.invitations.edit.header" %></h2>
|
|
2
|
+
|
|
3
|
+
<h3>
|
|
4
|
+
<%= resource.invited_by %>
|
|
5
|
+
te invitó a su cuenta en ProcuraBien
|
|
6
|
+
</h3>
|
|
7
|
+
<% if User.require_password_on_accepting %>
|
|
8
|
+
<p>
|
|
9
|
+
Para aceptar la invitación e ingresar al sistema por favor completá los siguientes datos:
|
|
10
|
+
</p>
|
|
11
|
+
<% end %>
|
|
12
|
+
<%= pg_form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :put }) do |f| %>
|
|
13
|
+
<%= f.hidden_field :invitation_token %>
|
|
14
|
+
|
|
15
|
+
<div class="form-inputs">
|
|
16
|
+
<% if f.object.class.require_password_on_accepting %>
|
|
17
|
+
<%= f.input :email, disabled: true %>
|
|
18
|
+
<%= f.input :nombre, required: true, autofocus: true %>
|
|
19
|
+
<%= f.input :apellido, required: true %>
|
|
20
|
+
<%= f.input :password,
|
|
21
|
+
required: true,
|
|
22
|
+
hint: (t('devise.shared.minimum_password_length', count: @minimum_password_length) if @minimum_password_length),
|
|
23
|
+
input_html: { autocomplete: "new-password" } %>
|
|
24
|
+
<%= f.input :password_confirmation,
|
|
25
|
+
required: true,
|
|
26
|
+
input_html: { autocomplete: "new-password" } %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<%= f.input :accept_terms, as: :boolean, label: t('attributes.accept_terms').html_safe, error_prefix: '' %>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="form-actions">
|
|
32
|
+
<%= f.button :submit, t("devise.invitations.edit.submit_button") %>
|
|
33
|
+
</div>
|
|
34
|
+
<% end %>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<h2><%= t "devise.invitations.new.header" %></h2>
|
|
2
|
+
<div style="max-width: 40em" data-controller="pg_form">
|
|
3
|
+
<%= pg_form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| %>
|
|
4
|
+
<div class="form-inputs">
|
|
5
|
+
<%= f.input :email, hint: 'Si la persona aún no tiene cuenta en ProcuraBien, se le enviará una invitación para que se registre' %>
|
|
6
|
+
</div>
|
|
7
|
+
<%= f.fields_for :user_accounts do |nf| %>
|
|
8
|
+
<%= render partial: 'tenant/user_accounts/fields', locals: { f: nf } %>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<div class="form-actions">
|
|
12
|
+
<%= f.button :submit, t("devise.invitations.new.submit_button"), class: 'btn btn-primary' %>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
15
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<p><%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %></p>
|
|
2
|
+
|
|
3
|
+
<p><%= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url) %></p>
|
|
4
|
+
|
|
5
|
+
<p><%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, invitation_token: @token) %></p>
|
|
6
|
+
|
|
7
|
+
<% if @resource.invitation_due_at %>
|
|
8
|
+
<p><%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %></p>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<p><%= t("devise.mailer.invitation_instructions.ignore") %></p>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %>
|
|
2
|
+
|
|
3
|
+
<%= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url) %>
|
|
4
|
+
|
|
5
|
+
<%= accept_invitation_url(@resource, invitation_token: @token) %>
|
|
6
|
+
|
|
7
|
+
<% if @resource.invitation_due_at %>
|
|
8
|
+
<%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %>
|
|
9
|
+
<% end %>
|
|
10
|
+
|
|
11
|
+
<%= t("devise.mailer.invitation_instructions.ignore") %>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<%= f.input :email, required: true, autofocus: true %>
|
|
6
6
|
<%= f.input :nombre, required: true %>
|
|
7
7
|
<%= f.input :apellido, required: true %>
|
|
8
|
+
<%= f.input :avatar %>
|
|
8
9
|
|
|
9
10
|
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
|
|
10
11
|
<p><%= t(".currently_waiting_confirmation_for_email", email: resource.unconfirmed_email) %></p>
|
|
@@ -51,6 +51,7 @@ html
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
body
|
|
54
|
+
span#tid.d-none data-tid="#{Current.tid}"
|
|
54
55
|
- sidebar_present = @navbar.present? && @sidebar != false
|
|
55
56
|
- if sidebar_present
|
|
56
57
|
= render partial: 'pg_layout/sidebar_mobile'
|
|
@@ -65,17 +66,18 @@ html
|
|
|
65
66
|
- if user_signed_in? && breadcrumbs.any?
|
|
66
67
|
.d-flex.d-print-none
|
|
67
68
|
.d-flex.flex-grow-1.px-3.py-1[
|
|
68
|
-
class="#{nav_bg} align-items-center
|
|
69
|
+
class="#{nav_bg} align-items-center xjustify-content-between gap-5"
|
|
69
70
|
style="min-height: 2.5em;"]
|
|
70
71
|
nav.d-flex aria-label="breadcrumb"
|
|
71
72
|
- unless frame_embedded?
|
|
72
|
-
i.bi-segmented-nav.me-2
|
|
73
|
+
i.bi-segmented-nav.me-2 style="transform: rotate(180deg);"
|
|
73
74
|
ol.breadcrumb
|
|
74
75
|
= render_breadcrumbs builder: PgEngine::Bootstrap5BreadcrumbsBuilder
|
|
75
|
-
|
|
76
|
+
.vr
|
|
76
77
|
.btn-toolbar.gap-1
|
|
77
78
|
= yield(:actions)
|
|
78
79
|
= yield(:extra_actions)
|
|
80
|
+
|
|
79
81
|
- if using_modal?
|
|
80
82
|
.px-2.d-flex.align-items-center.border.border-start-0
|
|
81
83
|
= button_tag type: :button, class: 'btn btn-sm btn-link',
|
|
@@ -96,7 +98,7 @@ html
|
|
|
96
98
|
|
|
97
99
|
/ hr.my-0
|
|
98
100
|
- content = content_for?(:content) ? yield(:content) : yield
|
|
99
|
-
/
|
|
101
|
+
/ TODO!!: rename to main?
|
|
100
102
|
- if (!turbo_frame? || current_turbo_frame == 'top') && \
|
|
101
103
|
content.exclude?('flash-container')
|
|
102
104
|
= render FlashContainerComponent.new
|
|
@@ -107,7 +109,7 @@ html
|
|
|
107
109
|
- if @no_main_frame
|
|
108
110
|
= captured_content
|
|
109
111
|
- else
|
|
110
|
-
/
|
|
112
|
+
/ TODO!!: rename to main, use a constant
|
|
111
113
|
= turbo_frame_tag current_turbo_frame || 'top',
|
|
112
114
|
**{ 'data-turbo-action': (turbo_frame? ? nil : :advance) }.compact do
|
|
113
115
|
= captured_content
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
<nav class="navbar navbar-expand-<%= @breakpoint_navbar_expand %>" data-bs-theme="dark">
|
|
2
|
-
<div class="container-fluid
|
|
2
|
+
<div class="container-fluid xgap-2">
|
|
3
3
|
<% unless @sidebar == false %>
|
|
4
4
|
<button data-controller="navbar" data-action="navbar#expandNavbar"
|
|
5
5
|
class="btn btn-outline-light me-2 d-none d-<%= @breakpoint_navbar_expand %>-inline-block">
|
|
6
6
|
<i class="bi <%= @navbar_chevron_class %>"></i>
|
|
7
7
|
</button>
|
|
8
|
-
|
|
9
8
|
<% end %>
|
|
9
|
+
<% if @navbar.logo.present? %>
|
|
10
|
+
<span class="ms-3">
|
|
11
|
+
<%= render @navbar.logo %>
|
|
12
|
+
</span>
|
|
13
|
+
<% end %>
|
|
14
|
+
<%= render partial: 'pg_layout/signed_in_links' %>
|
|
10
15
|
<% @navbar.extensiones.each do |extension| %>
|
|
11
16
|
<%= extension %>
|
|
12
17
|
<% end %>
|
|
13
|
-
<% if Current.user.present? && @notifications_bell.present? %>
|
|
14
|
-
<%= render @notifications_bell %>
|
|
15
|
-
<% end %>
|
|
16
|
-
<%= @navbar.logo if @navbar.logo.present? %>
|
|
17
18
|
<% unless @sidebar == false %>
|
|
18
19
|
<button class="btn btn-outline-light d-inline-block
|
|
19
20
|
d-<%= @breakpoint_navbar_expand %>-none"
|
|
@@ -1,27 +1,9 @@
|
|
|
1
1
|
<div id="sidebar" class="<%= @navbar_opened_class %> flex-shrink-0 d-none d-<%= @breakpoint_navbar_expand %>-block">
|
|
2
2
|
<div class="mt-1">
|
|
3
3
|
<div class="m-3">
|
|
4
|
-
<%= @navbar.logo if @navbar.logo.present? %>
|
|
4
|
+
<%= render @navbar.logo if @navbar.logo.present? %>
|
|
5
5
|
</div>
|
|
6
|
-
|
|
7
|
-
<span class="d-inline-block px-3 text-end text-light"><%= Current.user %></span>
|
|
8
|
-
<span class="d-block px-3 text-secondary">
|
|
9
|
-
<% if Current.user.user_accounts_without_tenant.count > 1 %>
|
|
10
|
-
<%= link_to ActsAsTenant.current_tenant, [:users, ActsAsTenant.current_tenant] if ActsAsTenant.current_tenant.present? %>
|
|
11
|
-
<%= link_to users_account_switcher_path do %>
|
|
12
|
-
<% if ActsAsTenant.current_tenant.present? %>
|
|
13
|
-
(Cambiar)
|
|
14
|
-
<% else %>
|
|
15
|
-
Elegir cuenta
|
|
16
|
-
<% end %>
|
|
17
|
-
<% end %>
|
|
18
|
-
<% else %>
|
|
19
|
-
<%= link_to ActsAsTenant.current_tenant, [:users, ActsAsTenant.current_tenant] if ActsAsTenant.current_tenant.present? %>
|
|
20
|
-
<% end %>
|
|
21
|
-
</span>
|
|
22
|
-
<hr>
|
|
23
|
-
<% end %>
|
|
24
|
-
<ul class="list-unstyled ps-0">
|
|
6
|
+
<ul class="list-unstyled ps-0 mt-5">
|
|
25
7
|
<% @navbar.sidebar.each do |entry| %>
|
|
26
8
|
<% next if @navbar.hide_entry?(entry) %>
|
|
27
9
|
|