bullet_train 1.0.25 → 1.0.28

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f53e93d30c7a323663e913316ef0d2b705a052ab3f8f075e0ea25bcfb233f8ec
4
- data.tar.gz: 8e33b7ca547682b3cc6b045167ecef56c133c15dd3b2e1996dd660af7871929b
3
+ metadata.gz: e9a2cb019fbf151b922e19e9ad2aec5f84ac7fd50045bd23d2ba94478c86a0dc
4
+ data.tar.gz: e63d7bb9128c48f49ee9e7b388c490173569624c2aaeb35d0c7a8d72d54c5abd
5
5
  SHA512:
6
- metadata.gz: 8a676d76f96eedefab979c6c6dd3b871351133fb799e0b0618748b2738831ab444e814ddfe3634cd19bd408ad844e43901eac091c836156039865e78618bb7b2
7
- data.tar.gz: 9f99942b4e68d2a21468fd557edaf14796482f69b385e5b1115af71eabce415d5968d418bb29525da65fd6d88344665cc06d5b4c2e6de0549bba02e76a6b39a5
6
+ metadata.gz: cbfa5d7e78cb1d62ad68966763a1c8d654c2ca6d080a3ad7a3d6e1126d0b46a44d96dcfeac454e368b5d58388dc2c5ab7f3d41122b8c03acb004e1447c2aced6
7
+ data.tar.gz: 73abfc993caaf2fbc71fccace9925bf8e897e35db76d4ef9c5cfe50495db45b33fecc924866da25a5b410e70d0a0f100da7f5a3f515cb4d681e2db68a60b1260
@@ -0,0 +1,6 @@
1
+ module BaseHelper
2
+ # TODO This is for the billing package to override, but I feel like there has got to be a better way to do this.
3
+ def hide_team_resource_menus?
4
+ false
5
+ end
6
+ end
@@ -0,0 +1,36 @@
1
+ module CurrentAttributes::Base
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ attribute :user, :team, :membership, :ability
6
+
7
+ resets do
8
+ Time.zone = nil
9
+ end
10
+ end
11
+
12
+ def user=(user)
13
+ super
14
+
15
+ if user
16
+ Time.zone = user.time_zone
17
+ self.ability = Ability.new(user)
18
+ else
19
+ Time.zone = nil
20
+ self.ability = nil
21
+ end
22
+
23
+ update_membership
24
+ end
25
+
26
+ def team=(team)
27
+ super
28
+ update_membership
29
+ end
30
+
31
+ def update_membership
32
+ self.membership = if user && team
33
+ user.memberships.where(team: team)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,305 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <%
6
+ # we're going to use the
7
+ body = Nokogiri::HTML(@body)
8
+ title = body.css('h1').first.text.presence || t('application.tagline')
9
+ first_paragraph = body.css('p').first
10
+ preceding_heading = first_paragraph&.xpath("preceding-sibling::h2")
11
+ description = [preceding_heading&.text, first_paragraph&.text].select(&:present?).join(" — ") || t('application.description')
12
+ image_url = "https://avatars.githubusercontent.com/u/5976880?s=280&amp;v=4"
13
+ site_name = "Bullet Train Developer Documentation"
14
+ %>
15
+
16
+ <% content_for :title do %>
17
+ <title><%= [site_name, title, t('application.tagline')].select(&:present?).uniq.first(2).reverse.join(' — ') %></title>
18
+ <% end %>
19
+
20
+ <%= render 'themes/light/layouts/head' %>
21
+ <meta content="<%= t('application.keywords') %>" name="keywords" />
22
+ <meta content="<%= description.truncate(200) %>" name="description" />
23
+ <meta name="twitter:image:src" content="<%= image_url %>" />
24
+ <meta name="twitter:site" content="@bullettrainco" />
25
+ <meta name="twitter:card" content="summary" />
26
+ <meta name="twitter:title" content="<%= title.truncate(70) %>" />
27
+ <meta name="twitter:description" content="<%= description.truncate(160) %>" />
28
+ <meta property="og:image" content="<%= image_url %>" />
29
+ <meta property="og:site_name" content="<%= site_name %>" />
30
+ <meta property="og:type" content="object" />
31
+ <meta property="og:title" content="<%= title.truncate(95) %>" />
32
+ <meta property="og:url" content="<%= request.base_url + request.path %>" />
33
+ <meta property="og:description" content="<%= description.truncate(200) %>" />
34
+ </head>
35
+ <body class="bg-light-blue-gradient text-gray-700 text-sm font-normal dark:bg-dark-blue-gradient dark:text-sealBlue-900">
36
+ <div class="md:p-5">
37
+ <div class="h-screen md:h-auto overflow-hidden md:rounded-lg flex shadow"
38
+ data-controller="mobile-menu"
39
+ data-mobile-menu-hidden-class="hidden"
40
+ data-mobile-menu-show-event-name-value="mobile-menu:show"
41
+ data-mobile-menu-hide-event-name-value="mobile-menu:hide"
42
+ >
43
+
44
+ <% menu = capture do %>
45
+ <div class="flex items-center flex-shrink-0 p-4 bg-blue-darker md:rounded-tl-lg">
46
+ <%= image_tag image_path("light/logo/logo.png"), class: 'h-5 w-auto mx-auto' %>
47
+
48
+ <div class="lg:hidden absolute right-0">
49
+ <button class="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
50
+ data-action="reveal#hide"
51
+ >
52
+ <span class="sr-only">Close Application Menu</span>
53
+ <svg class="h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
54
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
55
+ </svg>
56
+ </button>
57
+ </div>
58
+ </div>
59
+
60
+ <nav class="flex-1 space-y-1 overflow-y-auto">
61
+ <div class="px-5 py-4" id="menu">
62
+
63
+ <%= render 'account/shared/menu/section', title: 'Introduction' do %>
64
+ <%= render 'account/shared/menu/item', url: '/docs', label: 'Table of Contents' do |p| %>
65
+ <% p.content_for :icon do %>
66
+ <i class="fal fa-home-lg-alt ti ti-list"></i>
67
+ <% end %>
68
+ <% end %>
69
+
70
+ <%= render 'account/shared/menu/item', url: '/docs/getting-started', label: 'Getting Started' do |p| %>
71
+ <% p.content_for :icon do %>
72
+ <i class="fal fa-terminal ti ti-flag"></i>
73
+ <% end %>
74
+ <% end %>
75
+
76
+ <%= render 'account/shared/menu/item', url: '/docs/philosophy', label: 'Philosophy' do |p| %>
77
+ <% p.content_for :icon do %>
78
+ <i class="fal fa-lightbulb-on ti ti-light-bulb"></i>
79
+ <% end %>
80
+ <% end %>
81
+
82
+ <%= render 'account/shared/menu/item', url: '/docs/upgrades', label: 'Upgrades' do |p| %>
83
+ <% p.content_for :icon do %>
84
+ <i class="fal fa-sparkles ti ti-arrow-up"></i>
85
+ <% end %>
86
+ <% end %>
87
+
88
+ <%= render 'account/shared/menu/item', url: '/docs/tunneling', label: 'Tunneling' do |p| %>
89
+ <% p.content_for :icon do %>
90
+ <i class="fal fa-bolt ti ti-bolt"></i>
91
+ <% end %>
92
+ <% end %>
93
+ <% end %>
94
+
95
+ <%= render 'account/shared/menu/section', title: 'Developer Tools' do %>
96
+ <%= render 'account/shared/menu/item', url: '/docs/super-scaffolding', label: 'Super Scaffolding' do |p| %>
97
+ <% p.content_for :icon do %>
98
+ <i class="fal fa-magic ti ti-wand"></i>
99
+ <% end %>
100
+ <% end %>
101
+
102
+ <%= render 'account/shared/menu/item', url: '/docs/field-partials', label: 'Field Partials' do |p| %>
103
+ <% p.content_for :icon do %>
104
+ <i class="fal fa-i-cursor ti ti-text"></i>
105
+ <% end %>
106
+ <% end %>
107
+
108
+ <%= render 'account/shared/menu/item', url: '/docs/themes', label: 'Themes' do |p| %>
109
+ <% p.content_for :icon do %>
110
+ <i class="fal fa-swatchbook ti ti-palette"></i>
111
+ <% end %>
112
+ <% end %>
113
+
114
+ <%= render 'account/shared/menu/item', url: '/docs/seeds', label: 'Database Seeds' do |p| %>
115
+ <% p.content_for :icon do %>
116
+ <i class="fal fa-seedling ti ti-server"></i>
117
+ <% end %>
118
+ <% end %>
119
+
120
+ <%= render 'account/shared/menu/item', url: '/docs/testing', label: 'Test Suite' do |p| %>
121
+ <% p.content_for :icon do %>
122
+ <i class="fal fa-check ti ti-check"></i>
123
+ <% end %>
124
+ <% end %>
125
+ <% end %>
126
+
127
+ <%= render 'account/shared/menu/section', title: 'Accounts & Teams' do %>
128
+ <%= render 'account/shared/menu/item', url: '/docs/authentication', label: 'Authentication' do |p| %>
129
+ <% p.content_for :icon do %>
130
+ <i class="fal fa-fingerprint ti ti-id-badge"></i>
131
+ <% end %>
132
+ <% end %>
133
+
134
+ <%= render 'account/shared/menu/item', url: '/docs/teams', label: 'Teams' do |p| %>
135
+ <% p.content_for :icon do %>
136
+ <i class="fal fa-users ti ti-user"></i>
137
+ <% end %>
138
+ <% end %>
139
+
140
+ <%= render 'account/shared/menu/item', url: '/docs/permissions', label: 'Roles & Permissions' do |p| %>
141
+ <% p.content_for :icon do %>
142
+ <i class="fal fa-lock-alt ti ti-lock"></i>
143
+ <% end %>
144
+ <% end %>
145
+
146
+ <%= render 'account/shared/menu/item', url: '/docs/onboarding', label: 'Onboarding' do |p| %>
147
+ <% p.content_for :icon do %>
148
+ <i class="fal fa-snowboarding ti ti-direction"></i>
149
+ <% end %>
150
+ <% end %>
151
+
152
+ <%= render 'account/shared/menu/item', url: '/docs/namespacing', label: 'Namespacing' do |p| %>
153
+ <% p.content_for :icon do %>
154
+ <i class="fal fa-object-group ti ti-widgetized"></i>
155
+ <% end %>
156
+ <% end %>
157
+ <% end %>
158
+
159
+ <%= render 'account/shared/menu/section', title: 'Billing' do %>
160
+ <%= render 'account/shared/menu/item', url: '/docs/billing/stripe', label: 'Stripe' do |p| %>
161
+ <% p.content_for :icon do %>
162
+ <i class="fab fa-stripe-s ti ti-money"></i>
163
+ <% end %>
164
+ <% end %>
165
+ <% end %>
166
+
167
+ <%= render 'account/shared/menu/section', title: 'Integration' do %>
168
+ <%= render 'account/shared/menu/item', url: '/docs/oauth', label: 'OAuth Providers' do |p| %>
169
+ <% p.content_for :icon do %>
170
+ <i class="fal fa-at ti ti-reload"></i>
171
+ <% end %>
172
+ <% end %>
173
+
174
+ <%= render 'account/shared/menu/item', url: '/docs/api', label: 'REST API' do |p| %>
175
+ <% p.content_for :icon do %>
176
+ <i class="fal fa-brackets-curly ti ti-settings"></i>
177
+ <% end %>
178
+ <% end if false %>
179
+
180
+ <%= render 'account/shared/menu/item', url: '/docs/webhooks/outgoing', label: 'Outgoing Webhooks' do |p| %>
181
+ <% p.content_for :icon do %>
182
+ <i class="fal fa-outlet ti ti-pulse"></i>
183
+ <% end %>
184
+ <% end if false %>
185
+
186
+ <%= render 'account/shared/menu/item', url: '/docs/webhooks/incoming', label: 'Incoming Webhooks' do |p| %>
187
+ <% p.content_for :icon do %>
188
+ <i class="fal fa-plug ti ti-plug"></i>
189
+ <% end %>
190
+ <% end if false %>
191
+ <% end %>
192
+
193
+ <%= render 'account/shared/menu/section', title: 'Internationalization' do %>
194
+ <%= render 'account/shared/menu/item', url: '/docs/i18n', label: 'Translations' do |p| %>
195
+ <% p.content_for :icon do %>
196
+ <i class="fal fa-language ti ti-world"></i>
197
+ <% end %>
198
+ <% end %>
199
+ <% end if false %>
200
+
201
+ <%= render 'account/shared/menu/section', title: 'Add-Ons' do %>
202
+ <%= render 'account/shared/menu/item', url: '/docs/font-awesome-pro', label: 'Font Awesome Pro' do |p| %>
203
+ <% p.content_for :icon do %>
204
+ <i class="fal fa-flag ti ti-flag"></i>
205
+ <% end %>
206
+ <% end %>
207
+ <% end %>
208
+
209
+ <%= render 'account/shared/menu/section', title: 'Deployment' do %>
210
+ <%= render 'account/shared/menu/item', url: '/docs/heroku', label: 'Heroku' do |p| %>
211
+ <% p.content_for :icon do %>
212
+ <i class="fal fa-cloud ti ti-cloud-up"></i>
213
+ <% end %>
214
+ <% end %>
215
+
216
+ <%= render 'account/shared/menu/item', url: '/docs/desktop', label: 'Desktop Applications' do |p| %>
217
+ <% p.content_for :icon do %>
218
+ <i class="fal fa-window-restore ti ti-desktop"></i>
219
+ <% end %>
220
+ <% end %>
221
+ <% end %>
222
+ </div>
223
+ </nav>
224
+ <% end %>
225
+
226
+ <div class="lg:hidden hidden"
227
+ data-mobile-menu-target="wrapper"
228
+
229
+ data-controller="reveal"
230
+ data-reveal-away-value="true"
231
+ data-reveal-hide-keys-value="escape"
232
+
233
+ data-action="mobile-menu:show->reveal#show mobile-menu:hide->reveal#hide mobile-menu-toggle->reveal#toggle reveal:hidden->mobile-menu#hideWrapper"
234
+ >
235
+ <div class="fixed inset-0 flex z-40">
236
+ <button
237
+ data-action="reveal#hide"
238
+
239
+ hidden
240
+ data-reveal
241
+ data-transition
242
+ data-transition-enter="transition-opacity ease-linear duration-200"
243
+ data-transition-enter-start="opacity-0"
244
+ data-transition-enter-end="opacity-100"
245
+ data-transition-leave="transition-opacity ease-linear duration-200"
246
+ data-transition-leave-start="opacity-100"
247
+ data-transition-leave-end="opacity-0"
248
+
249
+ class="fixed inset-0" aria-hidden="true"
250
+ >
251
+ <div class="absolute inset-0 bg-light-blue-gradient opacity-75"></div>
252
+ </button>
253
+ <div
254
+ hidden
255
+ data-reveal
256
+ data-transition
257
+ data-transition-enter="transition ease-in-out duration-200 transform"
258
+ data-transition-enter-start="-translate-x-full"
259
+ data-transition-enter-end="translate-x-0"
260
+ data-transition-leave="transition ease-in-out duration-200 transform"
261
+ data-transition-leave-start="translate-x-0"
262
+ data-transition-leave-end="-translate-x-full"
263
+
264
+ class="relative flex-1 flex flex-col max-w-xs w-full shadow-xl bg-gradient-to-b from-vividBlue-700 to-vividBlue-800 dark:from-sealBlue-200 dark:to-sealBlue-200"
265
+ >
266
+ <%= menu %>
267
+ </div>
268
+ <div class="flex-shrink-0 w-14" aria-hidden="true"></div>
269
+ </div>
270
+ </div>
271
+
272
+ <div class="hidden lg:flex lg:flex-shrink-0 bg-gradient-to-b from-vividBlue-700 to-vividBlue-800 dark:from-sealBlue-200 dark:to-sealBlue-200">
273
+ <div class="w-64">
274
+ <%= menu %>
275
+ </div>
276
+ </div>
277
+
278
+ <div class="flex flex-col w-0 flex-1 overflow-hidden bg-gray-100 dark:bg-sealBlue-200 lg:border-l dark:border-gray-500">
279
+ <main class="flex-1 relative z-0 overflow-y-auto focus:outline-none" tabindex="0">
280
+
281
+ <button class="lg:hidden h-12 w-12 ml-1 flex-none inline-flex items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue"
282
+ data-action="mobile-menu#toggle"
283
+ >
284
+ <span class="sr-only">Open Application Menu</span>
285
+ <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
286
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
287
+ </svg>
288
+ </button>
289
+
290
+ <div class="py-2 px-1">
291
+ <div class="mx-auto sm:px-6 sm:py-4 px-2">
292
+ <div class="bg-white rounded-md shadow sm:py-14 sm:px-12 py-10 px-7">
293
+ <div class="prose" style="max-width: none;">
294
+ <%= yield %>
295
+ </div>
296
+ </div>
297
+
298
+ </div>
299
+ </div>
300
+ </main>
301
+ </div>
302
+ </div>
303
+ </div>
304
+ </body>
305
+ </html>
@@ -0,0 +1,65 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+ <title>Welcome to <%= t('application.name') %>!</title>
7
+ </head>
8
+ <body>
9
+ <% if content_for? :preheader %>
10
+ <span class="preheader"><% yield :preheader %></span>
11
+ <% end %>
12
+ <table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0">
13
+ <tr>
14
+ <td align="center">
15
+ <table class="email-content" width="100%" cellpadding="0" cellspacing="0">
16
+ <tr>
17
+ <td class="email-masthead">
18
+ <a href="<%= root_url %>" class="email-masthead_name">
19
+ <%= email_image_tag("light/logo/logo.png", width: image_width_for_height('light/logo/logo.png', 50), height: 50, style: "width: #{image_width_for_height('light/logo/logo.png', 50)}px; height: 50px;") %>
20
+ </a>
21
+ </td>
22
+ </tr>
23
+ <!-- Email Body -->
24
+ <tr>
25
+ <td class="email-body" width="100%" cellpadding="0" cellspacing="0">
26
+ <table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0">
27
+ <!-- Body content -->
28
+ <tr>
29
+ <td class="content-cell">
30
+
31
+ <%= yield %>
32
+
33
+ <% if false %>
34
+ <!-- Sub copy -->
35
+ <table class="body-sub">
36
+ <tr>
37
+ <td>
38
+ <p class="sub"><%= t('.trouble') %></p>
39
+ <p class="sub">{{action_url}}</p>
40
+ </td>
41
+ </tr>
42
+ </table>
43
+ <% end %>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+ </td>
48
+ </tr>
49
+ <tr>
50
+ <td>
51
+ <table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0">
52
+ <tr>
53
+ <td class="content-cell" align="center">
54
+ <p class="sub align-center">&copy; <%= t('.all_rights_reserved', year: Date.today.year, product_name: t('application.name')) %></p>
55
+ </td>
56
+ </tr>
57
+ </table>
58
+ </td>
59
+ </tr>
60
+ </table>
61
+ </td>
62
+ </tr>
63
+ </table>
64
+ </body>
65
+ </html>
@@ -0,0 +1 @@
1
+ <%= @body = markdown(File.read(Rails.root.to_s + "/docs/#{@file}.md").gsub('.md)', ')')) %>
@@ -0,0 +1,29 @@
1
+ <% content_for :preheader do %>
2
+ <%= t('.preview', @values) %>
3
+ <% end %>
4
+
5
+ <h1><%= t('.heading', @values) %></h1>
6
+ <%= t('.body.html', @values) %>
7
+
8
+ <!-- Action -->
9
+ <table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0">
10
+ <tr>
11
+ <td align="center">
12
+ <!-- Border based button https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
13
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
14
+ <tr>
15
+ <td align="center">
16
+ <table border="0" cellspacing="0" cellpadding="0">
17
+ <tr>
18
+ <td>
19
+ <a href="<%= @cta_url %>" class="button button--" target="_blank"><%= t('.cta.label', @values) %></a>
20
+ </td>
21
+ </tr>
22
+ </table>
23
+ </td>
24
+ </tr>
25
+ </table>
26
+ </td>
27
+ </tr>
28
+ </table>
29
+ <%= t('.signature.html', @values.merge({support_email: t('application.support_email')})) %>
@@ -0,0 +1,31 @@
1
+ <% content_for :preheader do %>
2
+ <%= t('.preview', @values) %>
3
+ <% end %>
4
+
5
+ <h1><%= t('.heading', @values) %></h1>
6
+ <%= t('.body.html', @values) %>
7
+
8
+ <h2><%= t('.cta.heading', @values) %></h2>
9
+ <p><%= t('.cta.body', @values) %></p>
10
+ <!-- Action -->
11
+ <table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0">
12
+ <tr>
13
+ <td align="center">
14
+ <!-- Border based button https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
15
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
16
+ <tr>
17
+ <td align="center">
18
+ <table border="0" cellspacing="0" cellpadding="0">
19
+ <tr>
20
+ <td>
21
+ <a href="<%= @cta_url %>" class="button button--" target="_blank"><%= t('.cta.label', @values) %></a>
22
+ </td>
23
+ </tr>
24
+ </table>
25
+ </td>
26
+ </tr>
27
+ </table>
28
+ </td>
29
+ </tr>
30
+ </table>
31
+ <%= t('.signature.html', @values.merge({support_email: t('application.support_email')})) %>
@@ -0,0 +1,127 @@
1
+ # Files in the config/locales directory are used for internationalization
2
+ # and are automatically loaded by Rails. If you want to use locales other
3
+ # than English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t "hello"
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t("hello") %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # The following keys must be escaped otherwise they will not be retrieved by
20
+ # the default I18n backend:
21
+ #
22
+ # true, false, on, off, yes, no
23
+ #
24
+ # Instead, surround them with single quotes.
25
+ #
26
+ # en:
27
+ # "true": "foo"
28
+ #
29
+ # To learn more, please read the Rails Internationalization guide
30
+ # available at https://guides.rubyonrails.org/i18n.html.
31
+
32
+ en:
33
+
34
+ global:
35
+ or: Or
36
+ more: More
37
+ is_admin: Admin?
38
+ person: Person
39
+ admin: Admin
40
+ confirm_message: Are you sure?
41
+ typing_search: Start typing search...
42
+ sidebar: Sidebar
43
+ creator: Bullet Train, Inc.
44
+ buttons:
45
+ other: Other
46
+ debug: Debug
47
+ details: Details
48
+ revoke: Revoke
49
+ cancel: Cancel
50
+ next: Next
51
+ back: Back
52
+ new: New
53
+ edit: Edit
54
+ settings: Settings
55
+ configure: Configure
56
+ remove: Remove
57
+ delete: Delete
58
+ update: Update
59
+ sign_up: Sign Up
60
+ sign_in: Sign In
61
+ notifications:
62
+ not_found: not found
63
+ all_fields_required: All of these fields are required.
64
+ dates:
65
+ today: Today
66
+ day:
67
+ one: 1 Day
68
+ other: '%{count} Days'
69
+ last_month: Last Month
70
+ last_week: Last Week
71
+ last_day:
72
+ one: Last Day
73
+ other: Last %{count} Days
74
+ formats:
75
+ date: '%m/%d/%Y'
76
+ date_and_time: '%m/%d/%Y %l:%M %p'
77
+
78
+ menus:
79
+ main:
80
+ labels:
81
+ account: Account
82
+ new: New
83
+ profile_details: Profile Details
84
+ logout: Logout
85
+ skip: Skip For Now
86
+ dashboard: Dashboard
87
+ team_members: Team Members
88
+ webhooks: Webhooks
89
+ invitations: Invitations
90
+ billing: Billing
91
+ upgrade: Upgrade
92
+ switch_teams: Switch Teams
93
+ add_new_team: Add New Team
94
+ edit_account_details: Account Details
95
+ resources: Resources
96
+ collaborate: Collaborate
97
+ integrations: Integrations
98
+ developers: Developers
99
+ your_account: Your Account
100
+
101
+ breadcrumbs:
102
+ your_dashboard: Your Dashboard
103
+ actions:
104
+ edit: 'Edit'
105
+ new: 'New'
106
+
107
+ fields:
108
+ date_field:
109
+ apply: Apply
110
+ cancel: Clear
111
+
112
+ layouts:
113
+
114
+ application:
115
+ raise: we should never be using the application layout.
116
+
117
+ mailer:
118
+ trouble: If you’re having trouble with the button above, copy and paste the URL below into your web browser.
119
+ all_rights_reserved: "%{year} %{product_name}. All rights reserved."
120
+
121
+ public:
122
+ launch_help: We're helping people launch high quality SaaS products!
123
+ developed_by: Developed By
124
+ made_with_love: Made With Love In
125
+ location: Los Angeles, California
126
+ follow_us: Follow Us
127
+ all_rights_reserved: "%{year} Bullet Train, Inc., All Rights Reserved"
@@ -0,0 +1,152 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ platform/application:
5
+ name: 'Name'
6
+ redirect_uri: 'Redirect URI'
7
+ errors:
8
+ models:
9
+ platform/application:
10
+ attributes:
11
+ redirect_uri:
12
+ fragment_present: 'cannot contain a fragment.'
13
+ invalid_uri: 'must be a valid URI.'
14
+ unspecified_scheme: 'must specify a scheme.'
15
+ relative_uri: 'must be an absolute URI.'
16
+ secured_uri: 'must be an HTTPS/SSL URI.'
17
+ forbidden_uri: 'is forbidden by the server.'
18
+ scopes:
19
+ not_match_configured: "can only contain the strings \"read\", \"write\", or \"delete\". You can also leave this field blank"
20
+
21
+ platform:
22
+ applications:
23
+ confirmations:
24
+ destroy: 'Are you sure?'
25
+ buttons:
26
+ edit: 'Edit'
27
+ destroy: 'Destroy'
28
+ submit: 'Submit'
29
+ cancel: 'Cancel'
30
+ authorize: 'Authorize'
31
+ form:
32
+ error: 'Whoops! Check your form for possible errors'
33
+ help:
34
+ confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
35
+ redirect_uri: 'Use one line per URI'
36
+ blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
37
+ scopes: 'Separate scopes with spaces. Leave blank to use the default scope.'
38
+ edit:
39
+ title: 'Edit application'
40
+ index:
41
+ title: 'Your applications'
42
+ new: 'New Application'
43
+ name: 'Name'
44
+ callback_url: 'Callback URL'
45
+ confidential: 'Confidential?'
46
+ actions: 'Actions'
47
+ confidentiality:
48
+ 'yes': 'Yes'
49
+ 'no': 'No'
50
+ new:
51
+ title: 'New Application'
52
+ show:
53
+ title: 'Application: %{name}'
54
+ application_id: 'UID'
55
+ secret: 'Secret'
56
+ secret_hashed: 'Secret hashed'
57
+ scopes: 'Scopes'
58
+ confidential: 'Confidential'
59
+ callback_urls: 'Callback urls'
60
+ actions: 'Actions'
61
+ not_defined: 'Not defined'
62
+
63
+ doorkeeper:
64
+ authorizations:
65
+ buttons:
66
+ authorize: 'Authorize'
67
+ deny: 'Deny'
68
+ error:
69
+ title: 'An error has occurred'
70
+ new:
71
+ title: 'Authorization required'
72
+ prompt: 'Authorize %{client_name} to use your account?'
73
+ able_to: 'This application will be able to'
74
+ show:
75
+ title: 'Authorization code'
76
+
77
+ authorized_applications:
78
+ confirmations:
79
+ revoke: 'Are you sure?'
80
+ buttons:
81
+ revoke: 'Revoke'
82
+ index:
83
+ title: 'Your authorized applications'
84
+ application: 'Application'
85
+ created_at: 'Created At'
86
+ date_format: '%Y-%m-%d %H:%M:%S'
87
+
88
+ pre_authorization:
89
+ status: 'Pre-authorization'
90
+
91
+ errors:
92
+ messages:
93
+ # Common error messages
94
+ invalid_request:
95
+ unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
96
+ missing_param: 'Missing required parameter: %{value}.'
97
+ not_support_pkce: 'Invalid code_verifier parameter. Server does not support pkce.'
98
+ request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
99
+ invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
100
+ unauthorized_client: 'The client is not authorized to perform this request using this method.'
101
+ access_denied: 'The resource owner or authorization server denied the request.'
102
+ invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
103
+ invalid_code_challenge_method: 'The code challenge method must be plain or S256.'
104
+ server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
105
+ temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
106
+
107
+ # Configuration error messages
108
+ credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
109
+ resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfigured.'
110
+ admin_authenticator_not_configured: 'Access to admin panel is forbidden due to Doorkeeper.configure.admin_authenticator being unconfigured.'
111
+
112
+ # Access grant errors
113
+ unsupported_response_type: 'The authorization server does not support this response type.'
114
+
115
+ # Access token errors
116
+ invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
117
+ invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
118
+ unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
119
+
120
+ invalid_token:
121
+ revoked: "The access token was revoked"
122
+ expired: "The access token expired"
123
+ unknown: "The access token is invalid"
124
+ revoke:
125
+ unauthorized: "You are not authorized to revoke this token"
126
+
127
+ flash:
128
+ applications:
129
+ create:
130
+ notice: 'Application created.'
131
+ destroy:
132
+ notice: 'Application deleted.'
133
+ update:
134
+ notice: 'Application updated.'
135
+ authorized_applications:
136
+ destroy:
137
+ notice: 'Application revoked.'
138
+
139
+ layouts:
140
+ admin:
141
+ title: 'Doorkeeper'
142
+ nav:
143
+ oauth2_provider: 'OAuth2 Provider'
144
+ applications: 'Applications'
145
+ home: 'Home'
146
+ application:
147
+ title: 'OAuth authorization required'
148
+
149
+ scopes:
150
+ delete: "Your OAuth application is missing the 'delete' scope to access this API method."
151
+ read: "Your OAuth application is missing the 'read' scope to access this API method."
152
+ write: "Your OAuth application is missing the 'write' scope to access this API method."
@@ -0,0 +1,15 @@
1
+ en:
2
+ stripe_connect: Stripe
3
+ # 🚅 super scaffolding will insert new oauth providers above this line.
4
+ omniauth:
5
+ team:
6
+ connected: "We've successfully added that %{provider} account to your team!"
7
+ denied: "Permission to connect to %{provider} was not granted. Not a problem! You can try again if you want to."
8
+ already_present: "That %{provider} account is already present for this team!"
9
+ not_allowed: "You're not allowed to add a %{provider} account to a team you don't have access to."
10
+ user:
11
+ connected: "We've successfully connected that %{provider} account to your user account."
12
+ reconnected: "That %{provider} account is already connected to your user account."
13
+ already_registered: "That %{provider} account is already connected to another user. Before you can connect that %{provider} account with your user account, you'll need to sign out and sign back in using that account and remove it from that user account profile."
14
+ email_already_registered: "Sorry, there is already a user registered with the email address %{email}, but this %{provider} account isn't configured for login with that account. Please sign in using your password and then add this account."
15
+ account_not_found: "Sorry, no existing account was found for that %{provider} account. In order to create a new account, please click the link in the invitation you received via email."
@@ -0,0 +1,6 @@
1
+ en:
2
+ roles:
3
+ label: &label Special Privileges
4
+ breadcrumbs:
5
+ label: *label
6
+ header: Special Privileges
@@ -0,0 +1,36 @@
1
+ en:
2
+ user_mailer:
3
+ signature: &SIGNATURE
4
+ html:
5
+ <p>If you have any questions, please don't hesitate to <a href="mailto:%{support_email}">send us an email</a>.</p>
6
+ <p>Thanks,<br>Bullet Train, Inc.</p>
7
+ invited:
8
+ subject: Invitation to join %{team_name} on Bullet Train!
9
+ preview: '%{inviter_name} has sent you this invitation.'
10
+ heading: You're invited!
11
+ body:
12
+ html:
13
+ <p>
14
+ %{inviter_name} has invited you to join %{team_name} on Bullet Train.
15
+ You can join %{team_name} by clicking the button below.
16
+ </p>
17
+ cta:
18
+ label: Join %{team_name}
19
+ signature:
20
+ <<: *SIGNATURE
21
+ welcome:
22
+ subject: Welcome to the Bullet Train demo!
23
+ preview: This is the default Bullet Train welcome email. Check out the layout!
24
+ heading: Welcome to Bullet Train!
25
+ body:
26
+ html:
27
+ <p>This is the default welcome email for Bullet Train!</p>
28
+ <p>If you have any questions about Bullet Train, just reply to this email!</p>
29
+ <p>It was important to us that Bullet Train applications have a good looking, branded email template by default.</p>
30
+ <p>Thankfully our friends at <a href="https://postmarkapp.com">Postmark</a> made the foundation of this email template <a href="https://github.com/wildbit/postmark-templates">freely available</a>. From there, we've customized it slightly to better match the default Bullet Train look-and-feel.</p>
31
+ cta:
32
+ heading: What's next?
33
+ body: You can use the following link to always return to your Bullet Train account dashboard.
34
+ label: View Your Account Dashboard
35
+ signature:
36
+ <<: *SIGNATURE
@@ -1,3 +1,3 @@
1
1
  module BulletTrain
2
- VERSION = "1.0.25"
2
+ VERSION = "1.0.28"
3
3
  end
data/lib/bullet_train.rb CHANGED
@@ -7,6 +7,9 @@ require "bullet_train/super_load_and_authorize_resource"
7
7
  require "bullet_train/has_uuid"
8
8
  require "bullet_train/scope_validator"
9
9
 
10
+ require "colorizer"
11
+ require "string/emoji"
12
+
10
13
  require "devise"
11
14
  # require "devise-two-factor"
12
15
  # require "rqrcode"
@@ -32,3 +35,86 @@ module BulletTrain
32
35
  mattr_accessor :routing_concerns, default: []
33
36
  mattr_accessor :linked_gems, default: ["bullet_train"]
34
37
  end
38
+
39
+ def default_url_options_from_base_url
40
+ unless ENV["BASE_URL"].present?
41
+ if Rails.env.development?
42
+ ENV["BASE_URL"] ||= "http://localhost:3000"
43
+ else
44
+ raise "you need to define the value of ENV['BASE_URL'] in your environment. if you're on heroku, you can do this with `heroku config:add BASE_URL=https://your-app-name.herokuapp.com` (or whatever your configured domain is)."
45
+ end
46
+ end
47
+
48
+ parsed_base_url = URI.parse(ENV["BASE_URL"])
49
+ default_url_options = [:user, :password, :host, :port].map { |key| [key, parsed_base_url.send(key)] }.to_h
50
+
51
+ # the name of this property doesn't match up.
52
+ default_url_options[:protocol] = parsed_base_url.scheme
53
+
54
+ default_url_options.compact
55
+ end
56
+
57
+ def inbound_email_enabled?
58
+ ENV["INBOUND_EMAIL_DOMAIN"].present?
59
+ end
60
+
61
+ def subscriptions_enabled?
62
+ false
63
+ end
64
+
65
+ def free_trial?
66
+ ENV["STRIPE_FREE_TRIAL_LENGTH"].present?
67
+ end
68
+
69
+ def stripe_enabled?
70
+ ENV["STRIPE_CLIENT_ID"].present?
71
+ end
72
+
73
+ # 🚅 super scaffolding will insert new oauth providers above this line.
74
+
75
+ def webhooks_enabled?
76
+ true
77
+ end
78
+
79
+ def scaffolding_things_disabled?
80
+ ENV["HIDE_THINGS"].present? || ENV["HIDE_EXAMPLES"].present?
81
+ end
82
+
83
+ def sample_role_disabled?
84
+ ENV["HIDE_EXAMPLES"].present?
85
+ end
86
+
87
+ def demo?
88
+ ENV["DEMO"].present?
89
+ end
90
+
91
+ def cloudinary_enabled?
92
+ ENV["CLOUDINARY_URL"].present?
93
+ end
94
+
95
+ def two_factor_authentication_enabled?
96
+ ENV["TWO_FACTOR_ENCRYPTION_KEY"].present?
97
+ end
98
+
99
+ def any_oauth_enabled?
100
+ [
101
+ stripe_enabled?,
102
+ # 🚅 super scaffolding will insert new oauth provider checks above this line.
103
+ ].select(&:present?).any?
104
+ end
105
+
106
+ def invitation_only?
107
+ ENV["INVITATION_KEYS"].present?
108
+ end
109
+
110
+ def invitation_keys
111
+ ENV["INVITATION_KEYS"].split(",").map(&:strip)
112
+ end
113
+
114
+ def font_awesome?
115
+ ENV["FONTAWESOME_NPM_AUTH_TOKEN"].present?
116
+ end
117
+
118
+ def multiple_locales?
119
+ @multiple_locales ||= I18n.available_locales.many?
120
+ end
data/lib/colorizer.rb ADDED
@@ -0,0 +1,67 @@
1
+ # https://makandracards.com/makandra/24449-hash-any-ruby-object-into-an-rgb-color
2
+ module Colorizer
3
+ extend self
4
+
5
+ def colorize(object)
6
+ # Inspired by Jeremy Ruten (http://stackoverflow.com/questions/1698318/ruby-generate-a-random-hex-color)
7
+ hash = object.hash # hash an object, returns a Fixnum
8
+ trimmed_hash = hash & 0xffffff # trim the hash to the size of 6 hex digits (& is bit-wise AND)
9
+ hex_code = "%06x" % trimmed_hash # format as at least 6 hex digits, pad with zeros
10
+ "##{hex_code}"
11
+ end
12
+
13
+ def colorize_similarly(object, saturation, lightness)
14
+ rnd = ((object.hash * 7) % 100) * 0.01
15
+ hsl_to_rgb(rnd, saturation, lightness)
16
+ end
17
+
18
+ private
19
+
20
+ def hsl_to_rgb(h, sl, l)
21
+ r = l
22
+ g = l
23
+ b = l
24
+ v = l <= 0.5 ? (l * (1.0 + sl)) : (l + sl - l * sl)
25
+ if v > 0
26
+ m = l + l - v
27
+ sv = (v - m) / v
28
+ h *= 6.0
29
+ sextant = h.floor
30
+ fract = h - sextant
31
+ vsf = v * sv * fract
32
+ mid1 = m + vsf
33
+ mid2 = v - vsf
34
+ case sextant
35
+ when 0
36
+ r = v
37
+ g = mid1
38
+ b = m
39
+ when 1
40
+ r = mid2
41
+ g = v
42
+ b = m
43
+ when 2
44
+ r = m
45
+ g = v
46
+ b = mid1
47
+ when 3
48
+ r = m
49
+ g = mid2
50
+ b = v
51
+ when 4
52
+ r = mid1
53
+ g = m
54
+ b = v
55
+ when 5
56
+ r = v
57
+ g = m
58
+ b = mid2
59
+ end
60
+ end
61
+ "##{hex_color_component(r)}#{hex_color_component(g)}#{hex_color_component(b)}"
62
+ end
63
+
64
+ def hex_color_component(i)
65
+ (i * 255).floor.to_s(16).rjust(2, "0")
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ class String
2
+ def strip_emojis
3
+ gsub(Unicode::Emoji::REGEX, "")
4
+ end
5
+
6
+ def only_emoji?
7
+ return false if strip.empty?
8
+ strip_emojis.strip.empty?
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.25
4
+ version: 1.0.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
@@ -391,6 +391,7 @@ files:
391
391
  - app/helpers/account/teams_helper.rb
392
392
  - app/helpers/account/users_helper.rb
393
393
  - app/helpers/attributes_helper.rb
394
+ - app/helpers/base_helper.rb
394
395
  - app/helpers/email_helper.rb
395
396
  - app/helpers/images_helper.rb
396
397
  - app/helpers/invitation_only_helper.rb
@@ -398,6 +399,7 @@ files:
398
399
  - app/mailers/concerns/mailers/base.rb
399
400
  - app/mailers/devise_mailer.rb
400
401
  - app/mailers/user_mailer.rb
402
+ - app/models/concerns/current_attributes/base.rb
401
403
  - app/models/concerns/invitations/base.rb
402
404
  - app/models/concerns/memberships/base.rb
403
405
  - app/models/concerns/records/base.rb
@@ -465,12 +467,22 @@ files:
465
467
  - app/views/devise/unlocks/new.html.erb
466
468
  - app/views/layouts/account.html.erb
467
469
  - app/views/layouts/devise.html.erb
470
+ - app/views/layouts/docs.html.erb
471
+ - app/views/layouts/mailer.html.erb
472
+ - app/views/public/home/docs.html.erb
473
+ - app/views/user_mailer/invited.html.erb
474
+ - app/views/user_mailer/welcome.html.erb
475
+ - config/locales/en/base.yml
468
476
  - config/locales/en/devise.en.yml
477
+ - config/locales/en/doorkeeper.en.yml
469
478
  - config/locales/en/invitations.en.yml
470
479
  - config/locales/en/memberships.en.yml
480
+ - config/locales/en/oauth.en.yml
471
481
  - config/locales/en/onboarding/user_details.en.yml
472
482
  - config/locales/en/onboarding/user_email.en.yml
483
+ - config/locales/en/roles.en.yml
473
484
  - config/locales/en/teams.en.yml
485
+ - config/locales/en/user_mailer.en.yml
474
486
  - config/locales/en/users.en.yml
475
487
  - config/routes.rb
476
488
  - db/migrate/20161115160419_devise_create_users.rb
@@ -511,6 +523,8 @@ files:
511
523
  - lib/bullet_train.rb
512
524
  - lib/bullet_train/engine.rb
513
525
  - lib/bullet_train/version.rb
526
+ - lib/colorizer.rb
527
+ - lib/string/emoji.rb
514
528
  - lib/tasks/bullet_train_tasks.rake
515
529
  homepage: https://github.com/bullet-train-co/bullet_train
516
530
  licenses: