bullet_train 1.1.3 → 1.1.5
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/app/controllers/concerns/account/memberships/controller_base.rb +9 -4
- data/app/helpers/account/teams_helper.rb +10 -0
- data/app/models/billing/mock_limiter.rb +9 -0
- data/app/models/concerns/memberships/base.rb +1 -1
- data/app/models/concerns/records/base.rb +4 -0
- data/app/models/concerns/teams/base.rb +10 -0
- data/app/views/account/invitations/_breadcrumbs.html.erb +1 -1
- data/app/views/account/invitations/_form.html.erb +40 -38
- data/app/views/account/memberships/_form.html.erb +0 -1
- data/app/views/account/memberships/_index.html.erb +56 -53
- data/config/locales/en/teams.en.yml +5 -1
- data/config/locales/en/users.en.yml +10 -2
- data/lib/bullet_train/version.rb +1 -1
- 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: a08595be0c53652a5cd5dfeeb920bc080476a31b180bb4832919398bcb0e2bf0
|
4
|
+
data.tar.gz: 8132b225ed537f17fd13c17a8d6edc4c99b63712d56cd208a5fda981074e819d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f6b84f79d914c69c184c1e0e8c9213eb0b8a000fcfbdc017768f5876408f99ec4a00c481e14c7f21ff9bc3de9652847c6ca37378e0446e153dbea918494bb94
|
7
|
+
data.tar.gz: 7d59102fd98d4b0fc7877be50b40285d4ef1597d694242e70b70e4d8807638220bbad1232ada6edafd8ab968767d3012ad78a1f7f2347ef220bf911a7447ce2c
|
@@ -84,11 +84,16 @@ module Account::Memberships::ControllerBase
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def reinvite
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
if helpers.current_limits.can?(:create, Membership)
|
88
|
+
@invitation = Invitation.new(membership: @membership, team: @team, email: @membership.user_email, from_membership: current_membership)
|
89
|
+
if @invitation.save
|
90
|
+
redirect_to [:account, @team, :memberships], notice: I18n.t("account.memberships.notifications.reinvited")
|
91
|
+
else
|
92
|
+
redirect_to [:account, @team, :memberships], notice: "There was an error creating the invitation (#{@invitation.errors.full_messages.to_sentence})"
|
93
|
+
end
|
90
94
|
else
|
91
|
-
|
95
|
+
flash[:error] = :create_limit
|
96
|
+
redirect_to [:account, @team, :memberships]
|
92
97
|
end
|
93
98
|
end
|
94
99
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Account::TeamsHelper
|
2
2
|
def current_team
|
3
|
+
# TODO We do not want this to be based on the `current_team_id`.
|
4
|
+
# TODO We want this to be based on the current resource being loaded.
|
3
5
|
current_user&.current_team
|
4
6
|
end
|
5
7
|
|
@@ -77,4 +79,12 @@ module Account::TeamsHelper
|
|
77
79
|
def can_invite?
|
78
80
|
can?(:create, Invitation.new(team: current_team))
|
79
81
|
end
|
82
|
+
|
83
|
+
def current_limits
|
84
|
+
@limiter ||= if billing_enabled? && defined?(Billing::Limiter)
|
85
|
+
Billing::Limiter.new(current_team)
|
86
|
+
else
|
87
|
+
Billing::MockLimiter.new(current_team)
|
88
|
+
end
|
89
|
+
end
|
80
90
|
end
|
@@ -4,6 +4,10 @@ module Records::Base
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
+
if billing_enabled? && defined?(Billing::UsageSupport)
|
8
|
+
include Billing::UsageSupport
|
9
|
+
end
|
10
|
+
|
7
11
|
if defined?(Webhooks::Outgoing::IssuingModel)
|
8
12
|
include Webhooks::Outgoing::IssuingModel
|
9
13
|
end
|
@@ -27,6 +27,10 @@ module Teams::Base
|
|
27
27
|
if defined?(Billing::Stripe::Subscription)
|
28
28
|
has_many :billing_stripe_subscriptions, class_name: "Billing::Stripe::Subscription", dependent: :destroy, foreign_key: :team_id
|
29
29
|
end
|
30
|
+
|
31
|
+
if defined?(Billing::Usage::TeamSupport)
|
32
|
+
include Billing::Usage::TeamSupport
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
# validations
|
@@ -62,6 +66,12 @@ module Teams::Base
|
|
62
66
|
|
63
67
|
# TODO Probably we can provide a way for gem packages to define these kinds of extensions.
|
64
68
|
if billing_enabled?
|
69
|
+
def current_billing_subscription
|
70
|
+
# If by some bug we have two subscriptions, we want to use the one that existed first.
|
71
|
+
# The reasoning here is that it's more likely to be on some legacy plan that benefits the customer.
|
72
|
+
billing_subscriptions.active.order(:created_at).first
|
73
|
+
end
|
74
|
+
|
65
75
|
def needs_billing_subscription?
|
66
76
|
return false if freemium_enabled?
|
67
77
|
billing_subscriptions.active.empty?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% invitation ||= @invitation %>
|
2
2
|
<% team ||= @team || invitation&.team %>
|
3
3
|
<%= render 'account/teams/breadcrumbs', team: team %>
|
4
|
-
<%= render 'account/shared/breadcrumb', label: t('.label'), url: [:account, team, :memberships] %>
|
4
|
+
<%= render 'account/shared/breadcrumb', label: t('memberships.label'), url: [:account, team, :memberships] %>
|
5
5
|
<%= render 'account/shared/breadcrumb', label: t('.label'), url: [:account, team, :invitations] %>
|
6
6
|
<% if invitation&.persisted? %>
|
7
7
|
<%= render 'account/shared/breadcrumb', label: invitation.label_string, url: [:account, invitation] %>
|
@@ -1,49 +1,51 @@
|
|
1
1
|
<%= form_with(model: [:account, (@team unless invitation.persisted?), invitation], class: 'form', local: true) do |form| %>
|
2
|
-
<%= render
|
2
|
+
<%= render "shared/limits/form", form: form, model: invitation.membership, cancel_path: @cancel_path || account_invitation_path(invitation) do %>
|
3
|
+
<%= render 'account/shared/forms/errors', form: form %>
|
3
4
|
|
4
|
-
|
5
|
+
<%= render 'shared/fields/email_field', form: form, method: :email, options: {autofocus: true} %>
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
<%= form.fields_for :membership do |membership_form| %>
|
8
|
+
<div class="grid grid-cols-1 gap-y gap-x sm:grid-cols-6">
|
9
|
+
<div class="sm:col-span-3">
|
10
|
+
<%= render 'shared/fields/text_field', form: membership_form, method: :user_first_name %>
|
11
|
+
</div>
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
<div class="sm:col-span-3">
|
14
|
+
<%= render 'shared/fields/text_field', form: membership_form, method: :user_last_name %>
|
15
|
+
</div>
|
14
16
|
</div>
|
15
|
-
|
16
|
-
<% end %>
|
17
|
+
<% end %>
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
19
|
+
<% if can? :manage, @team %>
|
20
|
+
<%= form.fields_for :membership do |fields| %>
|
21
|
+
<%= fields.hidden_field :team_id, value: @team.id %>
|
22
|
+
<div class="space-y-3">
|
23
|
+
<% Membership.assignable_roles.each do |role| %>
|
24
|
+
<% if current_membership.can_manage_role?(role) %>
|
25
|
+
<div class="flex items-top">
|
26
|
+
<%= fields.check_box :role_ids, {multiple: true, class: "h-4 w-4 text-blue focus:ring-blue-dark border-gray-300 rounded mt-0.5"}, role.id, nil %>
|
27
|
+
<label for="invitation_membership_attributes_role_ids_<%= role.id %>" class="ml-2 block select-none">
|
28
|
+
<span><%= t('invitations.form.invite_as', role_key: t("memberships.fields.role_ids.options.#{role.key}.label")) %></span>
|
29
|
+
<div class="mt-0.5 text-gray-400 font-light leading-normal">
|
30
|
+
<%= t("memberships.fields.role_ids.options.#{role.key}.description") %>
|
31
|
+
</div>
|
32
|
+
</label>
|
33
|
+
</div>
|
34
|
+
<% end %>
|
33
35
|
<% end %>
|
34
|
-
|
35
|
-
|
36
|
+
</div>
|
37
|
+
<% end %>
|
36
38
|
<% end %>
|
37
|
-
<% end %>
|
38
39
|
|
39
|
-
|
40
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
<div class="buttons">
|
43
|
+
<%= form.submit (form.object.persisted? ? t('.buttons.update') : t('.buttons.create')), class: "button" %>
|
44
|
+
<% if form.object.persisted? %>
|
45
|
+
<%= link_to t('global.buttons.cancel'), account_invitation_path(invitation), class: "button-secondary" %>
|
46
|
+
<% else %>
|
47
|
+
<%= link_to t('global.buttons.cancel'), @cancel_path || account_team_invitations_path(@team), class: "button-secondary" %>
|
48
|
+
<% end %>
|
49
|
+
</div>
|
50
|
+
<% end %>
|
49
51
|
<% end %>
|
@@ -2,65 +2,68 @@
|
|
2
2
|
<% hide_actions ||= false %>
|
3
3
|
<% hide_back ||= false %>
|
4
4
|
|
5
|
-
<%=
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
<%= updates_for context, :memberships do %>
|
6
|
+
<%= render 'account/shared/box' do |p| %>
|
7
|
+
<% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
|
8
|
+
<% p.content_for :description do %>
|
9
|
+
<%= raw t(".contexts.#{context.class.name.underscore}.#{memberships.any? ? 'description' : 'description_empty'}") %>
|
10
|
+
<%= render "shared/limits/index", model: memberships.model %>
|
11
|
+
<% end %>
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
13
|
+
<% p.content_for :table do %>
|
14
|
+
<% if memberships.any? %>
|
15
|
+
<table class="table">
|
16
|
+
<thead>
|
17
|
+
<tr>
|
18
|
+
<th><%= t('memberships.singular') %></th>
|
19
|
+
<th><%= t('memberships.fields.role_ids.heading') %></th>
|
20
|
+
<%# 🚅 super scaffolding will insert new field headers above this line. %>
|
21
|
+
<th></th>
|
22
|
+
</tr>
|
23
|
+
</thead>
|
24
|
+
<tbody data-model="Membership" data-scope="current">
|
25
|
+
<% memberships.each do |membership| %>
|
26
|
+
<tr data-id="<%= membership.id %>">
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
29
|
+
<%= link_to [:account, membership], class: 'block flex items-center group hover:no-underline no-underline' do %>
|
30
|
+
<div class="flex-shrink-0 h-10 w-10">
|
31
|
+
<%= image_tag membership_profile_photo_url(membership), title: membership.label_string, class: 'h-10 w-10 rounded-full' %>
|
32
|
+
</div>
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
34
|
+
<div class="ml-3">
|
35
|
+
<span class="group-hover:underline"><%= membership.label_string %></span>
|
36
|
+
<% if membership.unclaimed? %>
|
37
|
+
<span class="ml-1.5 px-2 inline-flex text-xs text-green-dark bg-green-light border border-green-dark rounded-md">
|
38
|
+
Invited
|
39
|
+
</span>
|
40
|
+
<% end %>
|
41
|
+
</div>
|
42
|
+
<% end %>
|
43
|
+
</td>
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
<td>
|
46
|
+
<% if membership.roles_without_defaults.any? %>
|
47
|
+
<%= membership.roles_without_defaults.map { |role| t("memberships.fields.role_ids.options.#{role.key}.label") }.to_sentence %>
|
48
|
+
<% else %>
|
49
|
+
<%= t("memberships.fields.role_ids.options.default.label") %>
|
50
|
+
<% end %>
|
51
|
+
</td>
|
52
|
+
<td class="text-right">
|
53
|
+
<%= link_to t('.buttons.show'), [:account, membership], class: 'button-secondary button-smaller' %>
|
54
|
+
</td>
|
55
|
+
</tr>
|
56
|
+
<% end %>
|
57
|
+
</tbody>
|
58
|
+
</table>
|
59
|
+
<% end %>
|
57
60
|
<% end %>
|
58
|
-
<% end %>
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
<% unless hide_actions %>
|
63
|
+
<% p.content_for :actions do %>
|
64
|
+
<%= link_to t('invitations.buttons.new'), new_account_team_invitation_path(@team, cancel_path: account_team_memberships_path(@team)), class: "#{first_button_primary}" %>
|
65
|
+
<%= link_to t('global.buttons.back'), [:account, context], class: "#{first_button_primary} back" unless hide_back %>
|
66
|
+
<% end %>
|
64
67
|
<% end %>
|
65
68
|
<% end %>
|
66
69
|
<% end %>
|
@@ -60,8 +60,11 @@ en:
|
|
60
60
|
heading: *locale
|
61
61
|
# 🚅 super scaffolding will insert new fields above this line.
|
62
62
|
created_at:
|
63
|
-
_: &created_at
|
63
|
+
_: &created_at Signed Up At
|
64
64
|
heading: *created_at
|
65
|
+
updated_at:
|
66
|
+
_: &updated_at Updated At
|
67
|
+
heading: *updated_at
|
65
68
|
_: &self
|
66
69
|
name:
|
67
70
|
label: Your Team Name
|
@@ -84,3 +87,4 @@ en:
|
|
84
87
|
locale: *locale
|
85
88
|
# 🚅 super scaffolding will insert new activerecord attributes above this line.
|
86
89
|
created_at: *created_at
|
90
|
+
updated_at: *updated_at
|
@@ -27,6 +27,10 @@ en:
|
|
27
27
|
notifications:
|
28
28
|
updated: User was successfully updated.
|
29
29
|
fields: &fields
|
30
|
+
id:
|
31
|
+
_: &id Team ID
|
32
|
+
label: *id
|
33
|
+
heading: *id
|
30
34
|
name:
|
31
35
|
heading: Name
|
32
36
|
first_name:
|
@@ -64,8 +68,11 @@ en:
|
|
64
68
|
help: By default the interface language will adjust based on each team's language setting, but you can set a global personal preference for your account here.
|
65
69
|
# 🚅 super scaffolding will insert new fields above this line.
|
66
70
|
created_at:
|
67
|
-
_: &created_at Signed Up
|
71
|
+
_: &created_at Signed Up At
|
68
72
|
heading: *created_at
|
73
|
+
updated_at:
|
74
|
+
_: &updated_at Updated At
|
75
|
+
heading: *updated_at
|
69
76
|
# this is how we define customizations to fields for a specific namespace.
|
70
77
|
_: &self
|
71
78
|
email:
|
@@ -105,6 +112,7 @@ en:
|
|
105
112
|
time_zone: *time_zone
|
106
113
|
locale: *locale
|
107
114
|
# 🚅 super scaffolding will insert new activerecord attributes above this line.
|
108
|
-
created_at: *created_at
|
109
115
|
password: *password
|
110
116
|
password_confirmation: *password_confirmation
|
117
|
+
created_at: *created_at
|
118
|
+
updated_at: *updated_at
|
data/lib/bullet_train/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet_train
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -483,6 +483,7 @@ files:
|
|
483
483
|
- app/mailers/concerns/mailers/base.rb
|
484
484
|
- app/mailers/devise_mailer.rb
|
485
485
|
- app/mailers/user_mailer.rb
|
486
|
+
- app/models/billing/mock_limiter.rb
|
486
487
|
- app/models/concerns/current_attributes/base.rb
|
487
488
|
- app/models/concerns/invitations/base.rb
|
488
489
|
- app/models/concerns/memberships/base.rb
|