bullet_train 1.1.9 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|