bullet_train 1.1.9 → 1.2.0
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/invitations/controller_base.rb +3 -11
- data/app/controllers/concerns/account/users/controller_base.rb +4 -25
- data/app/controllers/concerns/documentation_support.rb +1 -1
- data/app/controllers/concerns/registrations/controller_base.rb +9 -6
- data/app/controllers/sessions_controller.rb +9 -0
- data/app/helpers/account/teams_helper.rb +1 -1
- data/app/helpers/concerns/helpers/base.rb +0 -9
- data/app/javascript/controllers/index.js +2 -0
- data/app/javascript/controllers/select_all_controller.js +82 -0
- data/app/models/concerns/memberships/base.rb +3 -7
- data/app/models/concerns/users/base.rb +3 -0
- data/app/views/account/memberships/_index.html.erb +4 -35
- data/app/views/account/memberships/_membership.html.erb +29 -0
- data/app/views/account/memberships/index.html.erb +6 -1
- data/app/views/account/memberships/show.html.erb +1 -1
- data/app/views/account/onboarding/user_details/edit.html.erb +6 -6
- data/app/views/account/teams/_index.html.erb +1 -25
- data/app/views/account/teams/_team.html.erb +23 -0
- data/app/views/account/teams/index.html.erb +3 -1
- data/app/views/account/teams/show.html.erb +1 -1
- data/app/views/devise/registrations/new.html.erb +2 -2
- data/app/views/devise/sessions/new.html.erb +1 -1
- data/app/views/layouts/docs.html.erb +12 -0
- data/config/locales/en/base.yml +1 -0
- data/config/locales/en/framework_packages.yml +13 -17
- data/docs/application-options.md +29 -0
- data/docs/authentication.md +9 -0
- data/docs/field-partials/file-field.md +25 -0
- data/docs/field-partials.md +3 -1
- data/docs/i18n.md +28 -0
- data/docs/index.md +2 -0
- data/docs/invitation_only.md +1 -1
- data/docs/themes.md +13 -40
- data/docs/trademark.md +25 -0
- data/docs/two-factor-authentication.md +16 -0
- data/lib/bullet_train/resolver.rb +47 -0
- data/lib/bullet_train/version.rb +1 -1
- data/lib/bullet_train.rb +6 -1
- data/lib/colorizer.rb +1 -1
- data/lib/tasks/bullet_train_tasks.rake +74 -12
- metadata +9 -4
- data/app/assets/javascripts/bullet-train.js +0 -2
- data/app/assets/javascripts/bullet-train.js.map +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bb9dc7bc4b2ac1de4645e63ad3cf5da7bf2f4020365bf85efca8de4a4440a45
|
4
|
+
data.tar.gz: a328f4be111b4439a89ed0895bd92d16848fe81d9237e43c1f5def3759bed27a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f5892c3867e7ddb2530abe9516e004939c3dc8d35d1347d40e224a6e3d10d912fbb60d8cdc5ed62dcba895a459935ca1e7f3dd33b1b53f6dc31754de867895a
|
7
|
+
data.tar.gz: d2c9875372791ca7cf424da1141db44f1f31c2cb3b60cb6001ab80bf30a87bc63b7e52dd8c2808a9c8fcc412c9ee9419b8e137eb60f75439c3b5b30d0dd53811
|
@@ -49,17 +49,9 @@ module Account::Invitations::ControllerBase
|
|
49
49
|
|
50
50
|
# unless the user is signed in.
|
51
51
|
if !current_user.present?
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
session[:invitation_uuid] = params[:id]
|
56
|
-
|
57
|
-
# also, we'll queue devise up to return to the invitation url after a sign in.
|
58
|
-
session["user_return_to"] = request.path
|
59
|
-
|
60
|
-
# assume the user needs to create an account.
|
61
|
-
# this is not the default for devise, but a sensible default here.
|
62
|
-
redirect_to new_user_registration_path
|
52
|
+
# We need them to register.
|
53
|
+
# We have to send `invitation_uuid` via params, not session, because Safari doesn't set cookies on redirect.
|
54
|
+
redirect_to new_user_registration_path(invitation_uuid: @invitation&.uuid)
|
63
55
|
|
64
56
|
# session[:invitation_uuid] should only be present if the user is registering for the first time.
|
65
57
|
elsif (@invitation = Invitation.find_by(uuid: session[:invitation_uuid] || params[:id]))
|
@@ -10,6 +10,10 @@ module Account::Users::ControllerBase
|
|
10
10
|
# for magic locales.
|
11
11
|
@child_object = @user
|
12
12
|
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
include strong_parameters_from_api
|
13
17
|
end
|
14
18
|
|
15
19
|
# GET /account/users/1/edit
|
@@ -53,29 +57,4 @@ module Account::Users::ControllerBase
|
|
53
57
|
def process_params(strong_params)
|
54
58
|
raise "It looks like you've removed `process_params` from your controller. This will break Super Scaffolding."
|
55
59
|
end
|
56
|
-
|
57
|
-
# Never trust parameters from the scary internet, only allow the white list through.
|
58
|
-
# TODO Update this to use `include strong_parameters_from_api`.
|
59
|
-
def user_params
|
60
|
-
# TODO enforce permissions on updating the user's team name.
|
61
|
-
strong_params = params.require(:user).permit(
|
62
|
-
*([
|
63
|
-
:email,
|
64
|
-
:first_name,
|
65
|
-
:last_name,
|
66
|
-
:time_zone,
|
67
|
-
:current_password,
|
68
|
-
:password,
|
69
|
-
:password_confirmation,
|
70
|
-
:profile_photo_id,
|
71
|
-
:locale,
|
72
|
-
] + permitted_fields + [
|
73
|
-
{
|
74
|
-
current_team_attributes: [:name]
|
75
|
-
}.merge(permitted_arrays)
|
76
|
-
])
|
77
|
-
)
|
78
|
-
|
79
|
-
process_params(strong_params)
|
80
|
-
end
|
81
60
|
end
|
@@ -4,7 +4,7 @@ module DocumentationSupport
|
|
4
4
|
def docs
|
5
5
|
target = params[:page].presence || "index"
|
6
6
|
all_paths = ([Rails.root.to_s] + `bundle show --paths`.lines.map(&:chomp))
|
7
|
-
@path = all_paths.map { |path| path + "/docs/#{target}.md" }.detect { |path| File.
|
7
|
+
@path = all_paths.map { |path| path + "/docs/#{target}.md" }.detect { |path| File.exist?(path) }
|
8
8
|
render :docs, layout: "docs"
|
9
9
|
end
|
10
10
|
end
|
@@ -3,6 +3,12 @@ module Registrations::ControllerBase
|
|
3
3
|
|
4
4
|
included do
|
5
5
|
def new
|
6
|
+
# We have to set the session here because Safari wouldn't save it on a redirect to this URL.
|
7
|
+
if params[:invitation_uuid]
|
8
|
+
session[:invitation_uuid] = params[:invitation_uuid]
|
9
|
+
session["user_return_to"] = accept_account_invitation_path(params[:invitation_uuid])
|
10
|
+
end
|
11
|
+
|
6
12
|
if invitation_only?
|
7
13
|
unless session[:invitation_uuid] || session[:invitation_key]
|
8
14
|
return redirect_to root_path
|
@@ -19,17 +25,14 @@ module Registrations::ControllerBase
|
|
19
25
|
|
20
26
|
# if current_user is defined, that means they were successful registering.
|
21
27
|
if current_user
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
# so we don't have to create a default team for them here.
|
26
|
-
unless current_user.teams.any? || session[:invitation_uuid].present?
|
28
|
+
# Don't create a default team if they're being invited to another team.
|
29
|
+
# Don't create a default team if they have another one for any reason.
|
30
|
+
unless session[:invitation_uuid].present? || current_user.teams.any?
|
27
31
|
current_user.create_default_team
|
28
32
|
end
|
29
33
|
|
30
34
|
# send the welcome email.
|
31
35
|
current_user.send_welcome_email unless current_user.email_is_oauth_placeholder?
|
32
|
-
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
@@ -1,6 +1,15 @@
|
|
1
1
|
class SessionsController < Devise::SessionsController
|
2
2
|
include Sessions::ControllerBase
|
3
3
|
|
4
|
+
# If user_return_to points to an oauth path we disable Turbo on the sign in form.
|
5
|
+
# This makes it work when we need to redirect to external sites and/or custom protocols.
|
6
|
+
# With Turbo enabled the browser will block those redirects with a CORS error.
|
7
|
+
# https://github.com/bullet-train-co/bullet_train/issues/384
|
8
|
+
def user_return_to_is_oauth
|
9
|
+
session["user_return_to"]&.match(/^\/oauth/)
|
10
|
+
end
|
11
|
+
helper_method :user_return_to_is_oauth
|
12
|
+
|
4
13
|
def destroy
|
5
14
|
if params.include?(:onboard_logout)
|
6
15
|
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
@@ -2,7 +2,7 @@ module Account::TeamsHelper
|
|
2
2
|
def current_team
|
3
3
|
# TODO We do not want this to be based on the `current_team_id`.
|
4
4
|
# TODO We want this to be based on the current resource being loaded.
|
5
|
-
current_user&.current_team
|
5
|
+
@team || current_user&.current_team
|
6
6
|
end
|
7
7
|
|
8
8
|
def other_teams
|
@@ -6,13 +6,4 @@ module Helpers::Base
|
|
6
6
|
# This scope has an order if the SQL changes when we remove any order clause.
|
7
7
|
scope.to_sql != scope.reorder("").to_sql
|
8
8
|
end
|
9
|
-
|
10
|
-
# TODO This should really be in the API package and included from there.
|
11
|
-
if defined?(BulletTrain::Api)
|
12
|
-
def render_pagination(json)
|
13
|
-
if @pagy
|
14
|
-
json.has_more @pagy.has_more
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
9
|
end
|
@@ -6,6 +6,7 @@ import ClipboardController from './clipboard_controller'
|
|
6
6
|
import FormController from './form_controller'
|
7
7
|
import MobileMenuController from './mobile_menu_controller'
|
8
8
|
import TextToggleController from './text_toggle_controller'
|
9
|
+
import SelectAllController from './select_all_controller'
|
9
10
|
|
10
11
|
export const controllerDefinitions = [
|
11
12
|
[BulkActionFormController, 'bulk_action_form_controller.js'],
|
@@ -14,6 +15,7 @@ export const controllerDefinitions = [
|
|
14
15
|
[FormController, 'form_controller.js'],
|
15
16
|
[MobileMenuController, 'mobile_menu_controller.js'],
|
16
17
|
[TextToggleController, 'text_toggle_controller.js'],
|
18
|
+
[SelectAllController, 'select_all_controller.js'],
|
17
19
|
].map(function(d) {
|
18
20
|
const key = d[1]
|
19
21
|
const controller = d[0]
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = [ "checkbox", "toggleCheckbox", "toggleLabel", "wrapper" ]
|
5
|
+
static classes = [ "unavailable" ]
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
this.enableSelectAll()
|
9
|
+
}
|
10
|
+
|
11
|
+
enableSelectAll() {
|
12
|
+
if (!this.hasWrapperTarget) { return }
|
13
|
+
if (!this.hasUnavailableClass) { return }
|
14
|
+
|
15
|
+
this.wrapperTarget.classList.remove(this.unavailableClass)
|
16
|
+
this.updateToggle()
|
17
|
+
}
|
18
|
+
|
19
|
+
selectAllOrNone(event) {
|
20
|
+
event.preventDefault()
|
21
|
+
event.stopPropagation()
|
22
|
+
if (this.allSelected) {
|
23
|
+
this.selectNone()
|
24
|
+
} else {
|
25
|
+
this.selectAll()
|
26
|
+
}
|
27
|
+
this.updateToggle()
|
28
|
+
this.dispatch('toggled')
|
29
|
+
}
|
30
|
+
|
31
|
+
selectAll() {
|
32
|
+
this.checkboxTargets.forEach(checkbox => {
|
33
|
+
checkbox.checked = true
|
34
|
+
})
|
35
|
+
}
|
36
|
+
|
37
|
+
selectNone() {
|
38
|
+
this.checkboxTargets.forEach(checkbox => {
|
39
|
+
checkbox.checked = false
|
40
|
+
})
|
41
|
+
}
|
42
|
+
|
43
|
+
updateToggle() {
|
44
|
+
let checkbox = this.toggleCheckboxTarget
|
45
|
+
let useAlternateLabel = false
|
46
|
+
|
47
|
+
if (this.allSelected) {
|
48
|
+
if (checkbox) {
|
49
|
+
checkbox.checked = true
|
50
|
+
checkbox.indeterminate = false
|
51
|
+
}
|
52
|
+
useAlternateLabel = true
|
53
|
+
} else if (this.selectedValues.length > 0) {
|
54
|
+
if (checkbox) {
|
55
|
+
checkbox.indeterminate = true
|
56
|
+
}
|
57
|
+
} else {
|
58
|
+
if (checkbox) {
|
59
|
+
checkbox.checked = false
|
60
|
+
checkbox.indeterminate = false
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
if (this.hasToggleLabelTarget) {
|
65
|
+
this.toggleLabelTarget.dispatchEvent(new CustomEvent(`${this.identifier}:toggle-select-all-label`, { detail: { useAlternate: useAlternateLabel }} ))
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
get selectedValues() {
|
70
|
+
let values = []
|
71
|
+
this.checkboxTargets.forEach(checkbox => {
|
72
|
+
if (checkbox.checked) {
|
73
|
+
values.push(checkbox.value)
|
74
|
+
}
|
75
|
+
})
|
76
|
+
return values
|
77
|
+
}
|
78
|
+
|
79
|
+
get allSelected() {
|
80
|
+
return this.selectedValues.length === this.checkboxTargets.length
|
81
|
+
}
|
82
|
+
}
|
@@ -27,7 +27,7 @@ module Memberships::Base
|
|
27
27
|
|
28
28
|
scope :current_and_invited, -> { includes(:invitation).where("user_id IS NOT NULL OR invitations.id IS NOT NULL").references(:invitation) }
|
29
29
|
scope :current, -> { where("user_id IS NOT NULL") }
|
30
|
-
scope :tombstones, -> { includes(:invitation).where("user_id IS NULL AND invitations.id IS NULL").references(:invitation) }
|
30
|
+
scope :tombstones, -> { includes(:invitation).where("user_id IS NULL AND invitations.id IS NULL AND platform_agent IS FALSE").references(:invitation) }
|
31
31
|
|
32
32
|
# TODO Probably we can provide a way for gem packages to define these kinds of extensions.
|
33
33
|
if billing_enabled?
|
@@ -62,7 +62,7 @@ module Memberships::Base
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def tombstone?
|
65
|
-
user.nil? && invitation.nil? && !platform_agent
|
65
|
+
user.nil? && invitation.nil? && !platform_agent
|
66
66
|
end
|
67
67
|
|
68
68
|
def last_admin?
|
@@ -130,7 +130,7 @@ module Memberships::Base
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def first_name_last_initial
|
133
|
-
[first_name, last_initial].
|
133
|
+
[first_name, last_initial].select(&:present?).join(" ")
|
134
134
|
end
|
135
135
|
|
136
136
|
# TODO utilize this.
|
@@ -138,8 +138,4 @@ module Memberships::Base
|
|
138
138
|
def should_receive_notifications?
|
139
139
|
invitation.present? || user.present?
|
140
140
|
end
|
141
|
-
|
142
|
-
def platform_agent?
|
143
|
-
platform_agent_of_id.present?
|
144
|
-
end
|
145
141
|
end
|
@@ -109,10 +109,12 @@ module Users::Base
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
+
# TODO https://github.com/bullet-train-co/bullet_train-base/pull/121 should have removed this, but it caused errors.
|
112
113
|
def administrating_team_ids
|
113
114
|
parent_ids_for(Role.admin, :memberships, :team)
|
114
115
|
end
|
115
116
|
|
117
|
+
# TODO https://github.com/bullet-train-co/bullet_train-base/pull/121 should have removed this, but it caused errors.
|
116
118
|
def parent_ids_for(role, through, parent)
|
117
119
|
parent_id_column = "#{parent}_id"
|
118
120
|
key = "#{role.key}_#{through}_#{parent_id_column}s"
|
@@ -125,6 +127,7 @@ module Users::Base
|
|
125
127
|
value
|
126
128
|
end
|
127
129
|
|
130
|
+
# TODO https://github.com/bullet-train-co/bullet_train-base/pull/121 should have removed this, but it caused errors.
|
128
131
|
def invalidate_ability_cache
|
129
132
|
update_column(:ability_cache, {})
|
130
133
|
end
|
@@ -6,12 +6,12 @@
|
|
6
6
|
<%= render 'account/shared/box' do |p| %>
|
7
7
|
<% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
|
8
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 %>
|
9
|
+
<%= raw t(".contexts.#{context.class.name.underscore}.#{@memberships.any? ? 'description' : 'description_empty'}") %>
|
10
|
+
<%= render "shared/limits/index", model: @memberships.model %>
|
11
11
|
<% end %>
|
12
12
|
|
13
13
|
<% p.content_for :table do %>
|
14
|
-
<% if memberships.any? %>
|
14
|
+
<% if @memberships.any? %>
|
15
15
|
<table class="table">
|
16
16
|
<thead>
|
17
17
|
<tr>
|
@@ -22,38 +22,7 @@
|
|
22
22
|
</tr>
|
23
23
|
</thead>
|
24
24
|
<tbody data-model="Membership" data-scope="current">
|
25
|
-
|
26
|
-
<tr data-id="<%= membership.id %>">
|
27
|
-
|
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>
|
33
|
-
|
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>
|
44
|
-
|
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 %>
|
25
|
+
<%= yield %>
|
57
26
|
</tbody>
|
58
27
|
</table>
|
59
28
|
<% end %>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<tr data-id="<%= membership.id %>">
|
2
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
3
|
+
<%= link_to [:account, membership], class: 'block flex items-center group hover:no-underline no-underline' do %>
|
4
|
+
<div class="flex-shrink-0 h-10 w-10">
|
5
|
+
<%= image_tag membership_profile_photo_url(membership), title: membership.label_string, class: 'h-10 w-10 rounded-full' %>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div class="ml-3">
|
9
|
+
<span class="group-hover:underline"><%= membership.label_string %></span>
|
10
|
+
<% if membership.unclaimed? %>
|
11
|
+
<span class="ml-1.5 px-2 inline-flex text-xs text-green-dark bg-green-light border border-green-dark rounded-md">
|
12
|
+
Invited
|
13
|
+
</span>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
17
|
+
</td>
|
18
|
+
|
19
|
+
<td>
|
20
|
+
<% if membership.roles_without_defaults.any? %>
|
21
|
+
<%= membership.roles_without_defaults.map { |role| t("memberships.fields.role_ids.options.#{role.key}.label") }.to_sentence %>
|
22
|
+
<% else %>
|
23
|
+
<%= t("memberships.fields.role_ids.options.default.label") %>
|
24
|
+
<% end %>
|
25
|
+
</td>
|
26
|
+
<td class="text-right">
|
27
|
+
<%= link_to t('.buttons.show'), [:account, membership], class: 'button-secondary button-smaller' %>
|
28
|
+
</td>
|
29
|
+
</tr>
|
@@ -1,7 +1,12 @@
|
|
1
1
|
<%= render 'account/shared/page' do |p| %>
|
2
2
|
<% p.content_for :title, t('.section') %>
|
3
3
|
<% p.content_for :body do %>
|
4
|
-
|
4
|
+
<% if @memberships.current_and_invited.any? %>
|
5
|
+
<%= render 'index' do %>
|
6
|
+
<%= render @memberships.current_and_invited.includes(:user) %>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
9
|
+
|
5
10
|
<%= render 'tombstones', memberships: @memberships.tombstones.includes(:user) if @memberships.tombstones.any? %>
|
6
11
|
<% end %>
|
7
12
|
<% end %>
|
@@ -46,7 +46,7 @@
|
|
46
46
|
<% else %>
|
47
47
|
<%= link_to t('.buttons.promote'), [:promote, :account, @membership], method: :post, data: { confirm: t('global.confirm_message') }, class: first_button_primary if can? :promote, @membership %>
|
48
48
|
<% end %>
|
49
|
-
<% if (can? :destroy, @membership) && (!@membership.platform_agent
|
49
|
+
<% if (can? :destroy, @membership) && (!@membership.platform_agent) %>
|
50
50
|
<%= button_to t(".buttons.#{membership_destroy_locale_key(@membership)}"), [:account, @membership], method: :delete, data: { confirm: t(".buttons.confirmations.#{membership_destroy_locale_key(@membership)}", model_locales(@membership)) }, class: first_button_primary %>
|
51
51
|
<% end %>
|
52
52
|
<% end %>
|
@@ -16,15 +16,15 @@
|
|
16
16
|
<%= render 'shared/fields/text_field', form: f, method: :last_name %>
|
17
17
|
</div>
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
<% # only edit the team name if this user is an admin and they are the first user. %>
|
20
|
+
<% # yes, that's redundant. %>
|
21
|
+
<% if can?(:edit, f.object.current_team) && f.object.current_team.users.count == 1 %>
|
22
|
+
<div class="sm:col-span-2">
|
23
23
|
<%= f.fields_for :current_team do |tf| %>
|
24
24
|
<%= render 'shared/fields/text_field', form: tf, method: :name %>
|
25
25
|
<% end %>
|
26
|
-
|
27
|
-
|
26
|
+
</div>
|
27
|
+
<% end %>
|
28
28
|
|
29
29
|
<div class="sm:col-span-2">
|
30
30
|
<%= render 'shared/fields/super_select', form: f, method: :time_zone,
|
@@ -1,29 +1,5 @@
|
|
1
1
|
<ul class="space-y">
|
2
|
-
|
3
|
-
<li class="bg-white shadow overflow-hidden sm:rounded-md dark:bg-sealBlue-400">
|
4
|
-
<%= link_to [:account, team], class: "group block hover:bg-gray-50 dark:hover:bg-sealBlue-400 dark:text-sealBlue-800" do %>
|
5
|
-
<div class="px-4 py-4 flex items-center sm:pl-8 sm:pr-6">
|
6
|
-
<div class="min-w-0 flex-1 sm:flex sm:items-center sm:justify-between">
|
7
|
-
<div>
|
8
|
-
<div class="flex text-xl font-semibold text-blue uppercase group-hover:text-blue-dark tracking-widest dark:text-white">
|
9
|
-
<%= team.name %>
|
10
|
-
</div>
|
11
|
-
</div>
|
12
|
-
<div class="mt-4 flex-shrink-0 sm:mt-0">
|
13
|
-
<div class="flex overflow-hidden">
|
14
|
-
<%= render 'account/shared/memberships/photos', memberships: team.memberships.current_and_invited.first(10) %>
|
15
|
-
</div>
|
16
|
-
</div>
|
17
|
-
</div>
|
18
|
-
<div class="ml-5 flex-shrink-0">
|
19
|
-
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
20
|
-
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
21
|
-
</svg>
|
22
|
-
</div>
|
23
|
-
</div>
|
24
|
-
<% end %>
|
25
|
-
</li>
|
26
|
-
<% end %>
|
2
|
+
<%= yield %>
|
27
3
|
</ul>
|
28
4
|
|
29
5
|
<% if show_sign_up_options? && can?(:create, Team.new) %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<li class="bg-white shadow overflow-hidden sm:rounded-md dark:bg-sealBlue-400">
|
2
|
+
<%= link_to [:account, team], class: "group block hover:bg-gray-50 dark:hover:bg-sealBlue-400 dark:text-sealBlue-800" do %>
|
3
|
+
<div class="px-4 py-4 flex items-center sm:pl-8 sm:pr-6">
|
4
|
+
<div class="min-w-0 flex-1 sm:flex sm:items-center sm:justify-between">
|
5
|
+
<div>
|
6
|
+
<div class="flex text-xl font-semibold text-blue uppercase group-hover:text-blue-dark tracking-widest dark:text-white">
|
7
|
+
<%= team.name %>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
<div class="mt-4 flex-shrink-0 sm:mt-0">
|
11
|
+
<div class="flex overflow-hidden">
|
12
|
+
<%= render 'account/shared/memberships/photos', memberships: team.memberships.current_and_invited.first(10) %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<div class="ml-5 flex-shrink-0">
|
17
|
+
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
18
|
+
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
19
|
+
</svg>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
<% end %>
|
23
|
+
</li>
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<%= render 'account/shared/page' do |p| %>
|
2
2
|
<% p.content_for :title, t('.section') %>
|
3
3
|
<% p.content_for :body do %>
|
4
|
-
<%= render 'index', creative_concepts: @creative_concepts %>
|
4
|
+
<%= render 'index', creative_concepts: @creative_concepts do %>
|
5
|
+
<%= render @teams %>
|
6
|
+
<% end %>
|
5
7
|
<% end %>
|
6
8
|
<% end %>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<% unless scaffolding_things_disabled? %>
|
14
14
|
<%= render 'account/shared/commentary/box' do |p| %>
|
15
15
|
<% p.content_for :content do %>
|
16
|
-
<%= render 'account/scaffolding/absolutely_abstract/creative_concepts/index', creative_concepts: @team.scaffolding_absolutely_abstract_creative_concepts
|
16
|
+
<%= render 'account/scaffolding/absolutely_abstract/creative_concepts/index', creative_concepts: @team.scaffolding_absolutely_abstract_creative_concepts, hide_back: true unless scaffolding_things_disabled? %>
|
17
17
|
<% end %>
|
18
18
|
|
19
19
|
<% p.content_for :commentary do %>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<% p.content_for :title, t('devise.headers.sign_in') %>
|
3
3
|
<% p.content_for :body do %>
|
4
4
|
<% within_fields_namespace(:self) do %>
|
5
|
-
<%= form_for resource, as: resource_name, url: two_factor_authentication_enabled? ? users_pre_otp_path : session_path(resource_name), remote: two_factor_authentication_enabled?, html: {class: 'form'}, authenticity_token: true do |form| %>
|
5
|
+
<%= form_for resource, as: resource_name, url: two_factor_authentication_enabled? ? users_pre_otp_path : session_path(resource_name), remote: two_factor_authentication_enabled?, html: {class: 'form'}, authenticity_token: true, data: {turbo: !user_return_to_is_oauth} do |form| %>
|
6
6
|
<% with_field_settings form: form do %>
|
7
7
|
<%= render 'account/shared/notices', form: form %>
|
8
8
|
<%= render 'account/shared/forms/errors', form: form %>
|
@@ -108,6 +108,12 @@
|
|
108
108
|
<i class="fa-brands fa-js ti ti-pulse"></i>
|
109
109
|
<% end %>
|
110
110
|
<% end %>
|
111
|
+
|
112
|
+
<%= render 'account/shared/menu/item', url: '/docs/i18n', label: 'Internationalzation' do |p| %>
|
113
|
+
<% p.content_for :icon do %>
|
114
|
+
<i class="fa-brands fa-js ti ti-world"></i>
|
115
|
+
<% end %>
|
116
|
+
<% end %>
|
111
117
|
<% end %>
|
112
118
|
|
113
119
|
<%= render 'account/shared/menu/section', title: 'Developer Tools' do %>
|
@@ -140,6 +146,12 @@
|
|
140
146
|
<i class="fal fa-check ti ti-video-camera"></i>
|
141
147
|
<% end %>
|
142
148
|
<% end %>
|
149
|
+
|
150
|
+
<%= render 'account/shared/menu/item', url: 'docs/application-options.md', label: 'Application Options' do |p| %>
|
151
|
+
<% p.content_for :icon do %>
|
152
|
+
<i class="fal fa-gear ti ti-settings"></i>
|
153
|
+
<% end %>
|
154
|
+
<% end %>
|
143
155
|
<% end %>
|
144
156
|
|
145
157
|
<%= render 'account/shared/menu/section', title: 'Accounts & Teams' do %>
|
data/config/locales/en/base.yml
CHANGED
@@ -6,38 +6,34 @@ en:
|
|
6
6
|
bullet_train-api:
|
7
7
|
git: "bullet-train-co/bullet_train-api"
|
8
8
|
bullet_train-fields:
|
9
|
-
git: "bullet-train-co/bullet_train-
|
9
|
+
git: "bullet-train-co/bullet_train-core"
|
10
10
|
npm: "@bullet-train/fields"
|
11
11
|
bullet_train-has_uuid:
|
12
|
-
git: "bullet-train-co/bullet_train-
|
12
|
+
git: "bullet-train-co/bullet_train-core"
|
13
13
|
bullet_train-incoming_webhooks:
|
14
|
-
git: "bullet-train-co/bullet_train-
|
14
|
+
git: "bullet-train-co/bullet_train-core"
|
15
15
|
bullet_train-integrations:
|
16
|
-
git: "bullet-train-co/bullet_train-
|
16
|
+
git: "bullet-train-co/bullet_train-core"
|
17
17
|
bullet_train-integrations-stripe:
|
18
|
-
git: "bullet-train-co/bullet_train-
|
18
|
+
git: "bullet-train-co/bullet_train-core"
|
19
19
|
bullet_train-obfuscates_id:
|
20
|
-
git: "bullet-train-co/bullet_train-
|
20
|
+
git: "bullet-train-co/bullet_train-core"
|
21
21
|
bullet_train-outgoing_webhooks:
|
22
22
|
git: "bullet-train-co/bullet_train-outgoing_webhooks"
|
23
|
-
bullet_train-outgoing_webhooks-core:
|
24
|
-
git: "bullet-train-co/bullet_train-outgoing_webhooks-core"
|
25
23
|
bullet_train-scope_questions:
|
26
|
-
git: "bullet-train-co/bullet_train-
|
24
|
+
git: "bullet-train-co/bullet_train-core"
|
27
25
|
bullet_train-scope_validator:
|
28
|
-
git: "bullet-train-co/bullet_train-
|
26
|
+
git: "bullet-train-co/bullet_train-core"
|
29
27
|
bullet_train-sortable:
|
30
|
-
git: "bullet-train-co/bullet_train-
|
28
|
+
git: "bullet-train-co/bullet_train-core"
|
31
29
|
npm: "@bullet-train/bullet-train-sortable"
|
32
30
|
bullet_train-super_scaffolding:
|
33
31
|
git: "bullet-train-co/bullet_train-super_scaffolding"
|
34
32
|
bullet_train-super_load_and_authorize_resource:
|
35
|
-
git: "bullet-train-co/bullet_train-
|
33
|
+
git: "bullet-train-co/bullet_train-core"
|
36
34
|
bullet_train-themes:
|
37
|
-
git: "bullet-train-co/bullet_train-
|
38
|
-
bullet_train-themes-base:
|
39
|
-
git: "bullet-train-co/bullet_train-themes-base"
|
35
|
+
git: "bullet-train-co/bullet_train-core"
|
40
36
|
bullet_train-themes-light:
|
41
|
-
git: "bullet-train-co/bullet_train-
|
37
|
+
git: "bullet-train-co/bullet_train-core"
|
42
38
|
bullet_train-themes-tailwind_css:
|
43
|
-
git: "bullet-train-co/bullet_train-
|
39
|
+
git: "bullet-train-co/bullet_train-core"
|