bullet_train 1.6.30 → 1.6.31

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: ba0cb9d6382c0e48ac482c91eb3f207e449d0bed6c9f6f3f890fdf877aa0524f
4
- data.tar.gz: bee546685c3ec81e9f6709792ae7c0ec68573ce3ada9828d3dd3fc2385826e9a
3
+ metadata.gz: 4f095a907ffb4c58ff8e8f719eea4b1e4f4b800cf0784e54578ce0373485b2cd
4
+ data.tar.gz: 14d1cc067198dce1abc19bbc3edbf6c79007a9f73b073e97ed9d6ad3ccab5839
5
5
  SHA512:
6
- metadata.gz: 78a0773b19059db32d5b2e3ce35a0b53a185b4acff90b9908149e6446d5252d7b069cdecf4124793a468d4469a1e27a2d136a5ba5dc6937121badfdb2d786798
7
- data.tar.gz: fc58e373848016ac408541771b382c08ae252151e3ef07a88dfee9fb860de22f91e6fc9da074695277e18958431a545e1859258c0ecd84171ed177d1ea8f0777
6
+ metadata.gz: 57f1ed1e18979735a4801a02fe386e252c7b10c52d5619ab2c065b0a56aa0510c0c2bbfc81a43200ad4f88f644705ec9478cde3d09ef898a5ea60c42f85611a4
7
+ data.tar.gz: 9792cf9800fcbfe7c72a80ccf07723447ad2444fd084097632c31dd5292c033c71d20aabc441419ac8e700380d8c774cf1f5b266e591355ff49ed1f0c1380ee1
@@ -12,6 +12,6 @@ module Mailers::Base
12
12
  helper "account/users"
13
13
  helper "account/locale"
14
14
  helper "fields/trix_editor"
15
- helper "theme"
15
+ helper "current_theme"
16
16
  end
17
17
  end
@@ -0,0 +1,488 @@
1
+ # Installing Bullet-Train Themes on Jumpstart PRO Projects
2
+
3
+ Bullet Train themes can be installed on Jumpstart PRO projects, giving you native `erb` partials and Hotwire-powered UI components.
4
+
5
+ Like Jumpstart PRO, Bullet Train themes are built using `tailwindcss` and use `esbuild` and `postcss` for JavaScript and style sheets.
6
+
7
+ To get a quick sense of the UI components, we encourage you to spin up a Bullet Train project and navigate through the screens to create a "Creative Concept" and "Tangible Thing" resources.
8
+
9
+ In addition to providing a nice set of UI components, you'll get access to [`nice_partials`](https://github.com/bullet-train-co/nice_partials), Bullet-Train's own lightweight answer for creating `erb` partials with ad-hoc named content areas, which we think is just the right amount of magic for making `erb`-based components.
10
+
11
+ Note: we also have [instructions for installing themes on other Rails projects](on-other-rails-projects.md).
12
+
13
+ **Contents:**
14
+
15
+ 1. Installation Instructions
16
+ 2. Optional Configurations for switching colors, theme gems
17
+ 3. Using Locales for fields on new models
18
+ 4. Partials that require special instructions, exclusions
19
+ 5. Modifying ejected partials
20
+
21
+ ## 1. Installation Instructions
22
+
23
+ ### Add the theme gem
24
+
25
+ These instructions assume you're installing the `Light` theme bundled with Bullet Train.
26
+
27
+ ```
28
+ bundle add bullet_train-themes-light
29
+ ```
30
+
31
+ Or add the following to your `Gemfile`:
32
+
33
+ ```
34
+ gem "bullet_train-themes-light"
35
+ ```
36
+
37
+ And then run:
38
+
39
+ ```
40
+ bundle install
41
+ ```
42
+
43
+ ### Add `npm` packages
44
+
45
+ The `Light` theme requires the following npm packages to be installed
46
+
47
+ ```
48
+ yarn add @bullet-train/bullet-train @bullet-train/fields autoprefixer @rails/actiontext postcss-extend-rule
49
+ ```
50
+
51
+ Update your `app/javascript/controllers/index.js` with the following lines:
52
+
53
+ ```js
54
+ import { controllerDefinitions as bulletTrainControllers } from "@bullet-train/bullet-train"
55
+ import { controllerDefinitions as bulletTrainFieldControllers } from "@bullet-train/fields"
56
+
57
+ application.load(bulletTrainControllers)
58
+ application.load(bulletTrainFieldControllers)
59
+ ```
60
+
61
+ ### Add `bin/theme` and `bin/link` bin stubs
62
+
63
+ ```
64
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/bin/theme" -o bin/theme
65
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/bin/link" -o bin/link
66
+ chmod +x bin/theme bin/link
67
+ ```
68
+
69
+ ### Update `esbuild.config.mjs`
70
+
71
+ Replace it with these contents.
72
+
73
+ ```js
74
+ #!/usr/bin/env node
75
+
76
+ // Esbuild is configured with 3 modes:
77
+ //
78
+ // `yarn build` - Build JavaScript and exit
79
+ // `yarn build --watch` - Rebuild JavaScript on change
80
+ // `yarn build --reload` - Reloads page when views, JavaScript, or stylesheets change. Requires a PORT to listen on. Defaults to 3200 but can be specified with PORT env var
81
+ //
82
+ // Minify is enabled when "RAILS_ENV=production"
83
+ // Sourcemaps are enabled in non-production environments
84
+
85
+ import * as esbuild from "esbuild"
86
+ import path from "path"
87
+ import { execSync } from "child_process"
88
+ import rails from "esbuild-rails"
89
+ import chokidar from "chokidar"
90
+ import http from "http"
91
+ import { setTimeout } from "timers/promises"
92
+
93
+ let themeFile = ""
94
+ if (process.env.THEME) {
95
+ themeFile = execSync(`bundle exec bin/theme javascript ${process.env.THEME}`).toString().trim()
96
+ }
97
+
98
+ const themeEntrypoints = {}
99
+ if (process.env.THEME) {
100
+ themeEntrypoints[`application.${process.env.THEME}`] = themeFile
101
+ }
102
+
103
+ const clients = []
104
+ const entryPoints = {
105
+ "application": path.join(process.cwd(), "app/javascript/application.js"),
106
+ "administrate": path.join(process.cwd(), "app/javascript/administrate.js"),
107
+ ...themeEntrypoints,
108
+ }
109
+ const watchDirectories = [
110
+ "./app/javascript/**/*.js",
111
+ "./app/views/**/*.html.erb",
112
+ "./app/assets/builds/**/*.css", // Wait for cssbundling changes
113
+ "./config/locales/**/*.yml",
114
+ ]
115
+ const config = {
116
+ absWorkingDir: path.join(process.cwd(), "app/javascript"),
117
+ bundle: true,
118
+ entryPoints: entryPoints,
119
+ minify: process.env.RAILS_ENV == "production",
120
+ outdir: path.join(process.cwd(), "app/assets/builds"),
121
+ plugins: [rails()],
122
+ sourcemap: process.env.RAILS_ENV != "production",
123
+ define: {
124
+ global: "window"
125
+ },
126
+ loader: {
127
+ ".png": "file",
128
+ ".jpg": "file",
129
+ ".svg": "file",
130
+ ".woff": "file",
131
+ ".woff2": "file",
132
+ ".ttf": "file",
133
+ ".eot": "file",
134
+ }
135
+ }
136
+
137
+ async function buildAndReload() {
138
+ // Foreman & Overmind assign a separate PORT for each process
139
+ const port = parseInt(process.env.PORT || 3200)
140
+ console.log(`Esbuild is listening on port ${port}`)
141
+ const context = await esbuild.context({
142
+ ...config,
143
+ banner: {
144
+ js: ` (() => new EventSource("http://localhost:${port}").onmessage = () => location.reload())();`,
145
+ }
146
+ })
147
+
148
+ // Reload uses an HTTP server as an even stream to reload the browser
149
+ http
150
+ .createServer((req, res) => {
151
+ return clients.push(
152
+ res.writeHead(200, {
153
+ "Content-Type": "text/event-stream",
154
+ "Cache-Control": "no-cache",
155
+ "Access-Control-Allow-Origin": "*",
156
+ Connection: "keep-alive",
157
+ })
158
+ )
159
+ })
160
+ .listen(port)
161
+
162
+ await context.rebuild()
163
+ console.log("[reload] initial build succeeded")
164
+
165
+ let ready = false
166
+ chokidar
167
+ .watch(watchDirectories)
168
+ .on("ready", () => {
169
+ console.log("[reload] ready")
170
+ ready = true
171
+ })
172
+ .on("all", async (event, path) => {
173
+ if (ready === false) return
174
+
175
+ if (path.includes("javascript")) {
176
+ try {
177
+ await setTimeout(20)
178
+ await context.rebuild()
179
+ console.log("[reload] build succeeded")
180
+ } catch (error) {
181
+ console.error("[reload] build failed", error)
182
+ }
183
+ }
184
+ clients.forEach((res) => res.write("data: update\n\n"))
185
+ clients.length = 0
186
+ })
187
+ }
188
+
189
+ if (process.argv.includes("--reload")) {
190
+ buildAndReload()
191
+ } else if (process.argv.includes("--watch")) {
192
+ let context = await esbuild.context({...config, logLevel: 'info'})
193
+ context.watch()
194
+ } else {
195
+ esbuild.build(config)
196
+ }
197
+ ```
198
+
199
+ ### Update `tailwind.config.js`
200
+
201
+ Replace with these contents, which merge the Bullet Train-specific tailwind configs with those of Jumpstart PRO.
202
+
203
+ _Note: After this step, you might get an error on build about a missing `process.env.THEME`. Follow with the next step to fix this error._
204
+
205
+ ```js
206
+ const path = require('path');
207
+ const { execSync } = require("child_process");
208
+ const glob = require('glob').sync
209
+
210
+ if (!process.env.THEME) {
211
+ throw "tailwind.config.js: missing process.env.THEME"
212
+ process.exit(1)
213
+ }
214
+
215
+ const themeConfigFile = execSync(`bundle exec bin/theme tailwind-config ${process.env.THEME}`).toString().trim()
216
+ let themeConfig = require(themeConfigFile)
217
+
218
+ const colors = require('tailwindcss/colors')
219
+ const defaultTheme = require('tailwindcss/defaultTheme')
220
+
221
+ themeConfig.darkMode = 'class'
222
+
223
+ themeConfig.plugins.push(require('@tailwindcss/aspect-ratio'))
224
+
225
+ themeConfig.content = [
226
+ ...new Set([
227
+ ...themeConfig.content,
228
+ './app/components/**/*.rb',
229
+ './app/helpers/**/*.rb',
230
+ './app/javascript/**/*.js',
231
+ './app/views/**/*.erb',
232
+ './app/views/**/*.haml',
233
+ './app/views/**/*.slim',
234
+ './lib/jumpstart/app/views/**/*.erb',
235
+ './lib/jumpstart/app/helpers/**/*.rb'
236
+ ])
237
+ ]
238
+
239
+ themeConfig.theme.extend.colors = {
240
+ ...themeConfig.theme.extend.colors,
241
+ primary: colors.blue,
242
+ secondary: colors.emerald,
243
+ tertiary: colors.gray,
244
+ danger: colors.red,
245
+ gray: colors.neutral,
246
+ "code-400": "#fefcf9",
247
+ "code-600": "#3c455b",
248
+ }
249
+
250
+ themeConfig.theme.extend.fontFamily = {
251
+ ...themeConfig.theme.extend.fontFamily,
252
+ sans: ['Inter', ...defaultTheme.fontFamily.sans],
253
+ }
254
+
255
+ module.exports = themeConfig
256
+ ```
257
+
258
+ ### Update `build:css` in `package.json`
259
+
260
+ In `package.json`, replace the `build` and `build:css` entries under `scripts` with:
261
+
262
+ ```json
263
+ "build": "THEME=\"light\" node esbuild.config.mjs",
264
+ "build:css": "bin/link; THEME=\"light\" tailwindcss --postcss --minify -c ./tailwind.config.js -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.tailwind.css",
265
+ ```
266
+
267
+ ### Add `stylesheet_link_tag` to `<head>`
268
+
269
+ Make sure you have the following three lines in your `<head>`, which should be defined in `app/views/layouts/application.html.erb`:
270
+
271
+ ```erb
272
+ <%= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload" %>
273
+ <%= stylesheet_link_tag "application.tailwind", media: "all", "data-turbo-track": "reload" %>
274
+ <%= javascript_include_tag 'application.light', 'data-turbo-track': 'reload' %>
275
+ ```
276
+
277
+ ### Update `postcss.config.js`
278
+
279
+ Replace with these contents:
280
+
281
+ ```js
282
+ const { execSync } = require("child_process");
283
+
284
+ const postcssImportConfigFile = execSync(`bundle exec bin/theme postcss-import-config ${process.env.THEME}`).toString().trim()
285
+ const postcssImportConfig = require(postcssImportConfigFile)
286
+
287
+ module.exports = {
288
+ plugins: [
289
+ require('postcss-import')(postcssImportConfig),
290
+ require('postcss-extend-rule'),
291
+ require('tailwindcss/nesting'),
292
+ require('tailwindcss'),
293
+ require('autoprefixer')
294
+ ]
295
+ }
296
+ ```
297
+
298
+ ### Import the Theme Style Sheet
299
+
300
+ To your `application.tailwind.css` file, add the following line:
301
+
302
+ ```css
303
+ @import "$ThemeStylesheetsDir/application.css";
304
+ ```
305
+
306
+ ### Add Themify Icons, jQuery (for now) and trix editor support
307
+
308
+ Note: jQuery is needed for some of our components, but defining `window.$` won't be required soon. See PR https://github.com/bullet-train-co/bullet_train-core/pull/765
309
+
310
+ ```
311
+ yarn add @icon/themify-icons jquery
312
+ ```
313
+
314
+ To your `application.js`, add the following line:
315
+
316
+ ```js
317
+ import jquery from "jquery"
318
+ window.jQuery = jquery
319
+ window.$ = jquery
320
+
321
+ require("@icon/themify-icons/themify-icons.css")
322
+
323
+ import { trixEditor } from "@bullet-train/fields"
324
+ trixEditor()
325
+ ```
326
+
327
+ ### Add Locale Strings
328
+
329
+ Add these to your `config/locales/en.yml` under `en:`
330
+
331
+ ```yml
332
+ date:
333
+ formats:
334
+ date_field: "%m/%d/%Y"
335
+ date_and_time_field: "%m/%d/%Y %l:%M %p"
336
+ date_controller: "MM/DD/YYYY"
337
+ time:
338
+ am: AM
339
+ pm: PM
340
+ formats:
341
+ date_field: "%m/%d/%Y"
342
+ date_and_time_field: "%m/%d/%Y %l:%M %p"
343
+ date_controller: "MM/DD/YYYY h:mm A"
344
+ daterangepicker:
345
+ firstDay: 1
346
+ separator: " - "
347
+ applyLabel: "Apply"
348
+ cancelLabel: "Cancel"
349
+ fromLabel: "From"
350
+ toLabel: "To"
351
+ customRangeLabel: "Custom"
352
+ weekLabel: "W"
353
+ daysOfWeek:
354
+ - "Su"
355
+ - "Mo"
356
+ - "Tu"
357
+ - "We"
358
+ - "Th"
359
+ - "Fr"
360
+ - "Sa"
361
+ monthNames:
362
+ - "January"
363
+ - "February"
364
+ - "March"
365
+ - "April"
366
+ - "May"
367
+ - "June"
368
+ - "July"
369
+ - "August"
370
+ - "September"
371
+ - "October"
372
+ - "November"
373
+ - "December"
374
+ date_range_controller:
375
+ today: Today
376
+ yesterday: yesterday
377
+ last7Days: Last 7 Days
378
+ last30Days: Last 30 Days
379
+ thisMonth: This Month
380
+ lastMonth: Last Month
381
+ global:
382
+ buttons:
383
+ other: Other
384
+ cancel: Cancel
385
+ bulk_select:
386
+ all: All
387
+ ```
388
+
389
+ ### Disable `display: block` on `label` elements
390
+
391
+ In `app/assets/stylesheets/components/forms.css`, find the line under `label {`:
392
+
393
+ ```css
394
+ @apply block text-sm font-medium leading-5 text-gray-700 mb-1;
395
+ ```
396
+
397
+ And remove the `block` token:
398
+
399
+ ```css
400
+ @apply text-sm font-medium leading-5 text-gray-700 mb-1;
401
+ ```
402
+
403
+ ## 2. Optional Configurations for switching colors, theme gems
404
+
405
+ ### For Setting the Active Color
406
+
407
+ ```
408
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/initializers/theme.rb" -o initializers/theme.rb
409
+ ```
410
+
411
+ Add the following classes to your `html` tag for your layout:
412
+
413
+ ```erb
414
+ <html class="theme-<%= BulletTrain::Themes::Light.color %> <%= "theme-secondary-#{BulletTrain::Themes::Light.secondary_color}" if BulletTrain::Themes::Light.secondary_color %>"
415
+ ```
416
+
417
+ ### For Switching Between Installed Themes
418
+
419
+ If you'd like to create your own theme but would still like to build on top of `:light`, you'll need to have both gems installed and you'll be able to switch the current theme this way.
420
+
421
+ Define `current_theme` in `app/helpers/application_helper.rb`
422
+
423
+ ```
424
+ module ApplicationHelper
425
+ def current_theme
426
+ :light
427
+ end
428
+ end
429
+ ```
430
+
431
+ To change to use a different theme:
432
+
433
+ 1. Change the value returned by `current_theme` to the new theme name
434
+ 2. Change the name of the `THEME` env var defined in `build` and `build:css` in `package.json`
435
+ 3. Change the name of the theme in the `javascript_include_tag` in the `<head>`.
436
+
437
+ ## 3. Using Locales for fields on new models
438
+
439
+ The theme's field partials work best with locale strings that are defined for the model you're creating.
440
+
441
+ Example: you've created a Project model. Here we'll create a `projects.en.yml`
442
+
443
+ 1. Run `curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train-core/main/bullet_train-super_scaffolding/config/locales/en/scaffolding/completely_concrete/tangible_things.en.yml" -o config/locales/projects.en.yml`
444
+ 2. Search and replace `projects.en.yml` for `scaffolding/completely_concrete/tangible_things`, `Tangible Things`, `Tangible Thing`, `tangible_things` and `tangible_thing`. Replace with `projects`, `Projects`, `Project`, `projects` and `project` respectively.
445
+ 3. Remove strings you won't be using. In particular, look for comments with "skip" or "scaffolding".
446
+
447
+ Some fields use locale strings to drive their `options`. In the `tangible_things.en.yml` template file, look for `super_select_value`, `multiple_option_values` and others.
448
+
449
+ You'll notice `&` and `*` symbols prefixing some special keys in the `yml` file. Those are anchors and aliases and they help you reduce repetition in your locale strings.
450
+
451
+ To learn more about how these locales are generated in Bullet Train, see the documentation on [Bullet Train's Super Scaffolding](/docs/super-scaffolding.md)
452
+
453
+ ## 4. Partials that require special instructions, exclusions
454
+
455
+ ### For using boolean-type fields (options, buttons)
456
+
457
+ In `ApplicationController`, add this:
458
+
459
+ ```ruby
460
+ include Fields::ControllerSupport
461
+ ```
462
+
463
+ ### For the file_field partial
464
+
465
+ ```ruby
466
+ # in the model
467
+ has_one_attached :file_field_value
468
+ after_validation :remove_file_field_value, if: :file_field_value_removal?
469
+ attr_accessor :file_field_value_removal
470
+ def file_field_value_removal?
471
+ def remove_file_field_value
472
+ ```
473
+
474
+ ```ruby
475
+ # in the controller's strong_params
476
+ :file_field_value,
477
+ :file_field_value_removal,
478
+ ```
479
+
480
+ ### For `image`, `active_storage_image`
481
+
482
+ See [`account/users_helper` in BT core repo](https://github.com/bullet-train-co/bullet_train-core/blob/main/bullet_train/app/helpers/account/users_helper.rb) for implementing `photo_url_for_active_storage_attachment`
483
+
484
+ ## 5. Modifying ejected partials
485
+
486
+ ### For ejecting a theme partial and modifying it
487
+
488
+ We recommend firing up a Bullet-Train project and using its `bin/resolve` (see docs on [Indirection](indirection)) to get a copy of the partial field locally to modify.
@@ -0,0 +1,301 @@
1
+ # Installing Bullet-Train Themes on Other Rails Projects
2
+
3
+ Bullet Train themes can be installed on Vanilla Rails projects.
4
+
5
+ Our main theme, called `Light`, uses `erb` partials to give you native Rails views with Hotwire-powered components. It's built on `tailwindcss`, uses `postcss` to allow for local CSS overrides and uses `esbuild` for fast javascript compilation and to support javascript-side CSS imports.
6
+
7
+ In addition to providing a nice set of UI components, you'll get access to [`nice_partials`](https://github.com/bullet-train-co/nice_partials), Bullet-Train's own lightweight answer for creating `erb` partials with ad-hoc named content areas, which we think is just the right amount of magic for making `erb`-based components.
8
+
9
+ Note: we have [special instructions for installing themes on Jumpstart PRO projects](on-jumpstart-pro-projects.md).
10
+
11
+ **Contents:**
12
+
13
+ 1. Installation Instructions
14
+ 2. Optional Configurations for switching colors, theme gems
15
+ 3. Using Locales for fields on new models
16
+ 4. Partials that require special instructions, exclusions
17
+ 5. Modifying ejected partials
18
+
19
+ ## 1. Installation Instructions
20
+
21
+ ### Ensure your Rails Project uses `esbuild` and `tailwindcss` with `postcss`
22
+
23
+ You'll need to make sure your Rails project is set up to use `esbuild`, `tailwindcss` and `postcss`.
24
+
25
+ The easiest way to see what your project should include is to create a separate project, for reference, generated via this command:
26
+
27
+ ```
28
+ rails new rails-new-esbuild-tailwind-postcss --css tailwind --javascript esbuild
29
+ ```
30
+
31
+ ### Add the theme gem
32
+
33
+ These instructions assume you're installing the `Light` theme bundled with Bullet Train.
34
+
35
+ ```
36
+ bundle add bullet_train-themes-light
37
+ ```
38
+
39
+ Or add the following to your `Gemfile`:
40
+
41
+ ```
42
+ gem "bullet_train-themes-light"
43
+ ```
44
+
45
+ And then run:
46
+
47
+ ```
48
+ bundle install
49
+ ```
50
+
51
+ ### Add `npm` packages
52
+
53
+ The `Light` theme requires the following npm packages to be installed
54
+
55
+ ```
56
+ yarn add @bullet-train/bullet-train @bullet-train/fields autoprefixer @rails/actiontext postcss-extend-rule postcss-import
57
+ ```
58
+
59
+ Update your `app/javascript/controllers/index.js` with the following lines:
60
+
61
+ ```js
62
+ import { controllerDefinitions as bulletTrainControllers } from "@bullet-train/bullet-train"
63
+ import { controllerDefinitions as bulletTrainFieldControllers } from "@bullet-train/fields"
64
+
65
+ application.load(bulletTrainControllers)
66
+ application.load(bulletTrainFieldControllers)
67
+ ```
68
+
69
+ ### Overwrite tailwind and esbuild config files, add bin stubs from Bullet Train
70
+
71
+ ```
72
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/esbuild.config.js" -o esbuild.config.js
73
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/postcss.config.js" -o postcss.config.js
74
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/tailwind.config.js" -o tailwind.config.js
75
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/bin/theme" -o bin/theme
76
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/bin/link" -o bin/link
77
+ chmod +x bin/theme bin/link
78
+
79
+ ```
80
+
81
+ ### Update `build:css` in `package.json`
82
+
83
+ In `package.json`, replace the `build` and `build:css` entries under `scripts` with:
84
+
85
+ ```json
86
+ "build": "THEME=\"light\" node esbuild.config.js",
87
+ "build:css": "bin/link; THEME=\"light\" tailwindcss --postcss --minify -c ./tailwind.config.js -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.tailwind.css"
88
+ ```
89
+ ### Update esbuild.config.js
90
+
91
+ Remove or comment out the following line from `esbuild.config.js`:
92
+
93
+ ```js
94
+ "intl-tel-input-utils": path.join(process.cwd(), "app/javascript/intl-tel-input-utils.js"),
95
+ ```
96
+
97
+ ### Add `stylesheet_link_tag` to `<head>`
98
+
99
+ Make sure you have the following three lines in your `<head>`, which should be defined in `app/views/layouts/application.html.erb`:
100
+
101
+ ```erb
102
+ <%= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload" %>
103
+ <%= stylesheet_link_tag "application.tailwind", media: "all", "data-turbo-track": "reload" %>
104
+ <%= javascript_include_tag 'application.light', 'data-turbo-track': 'reload' %>
105
+ ```
106
+
107
+ ### Import the Theme Style Sheet
108
+
109
+ To your `application.tailwind.css` file, add the following line:
110
+
111
+ ```css
112
+ @import "$ThemeStylesheetsDir/application.css";
113
+ ```
114
+
115
+ Also be sure to replace the following lines:
116
+
117
+ ```css
118
+ @tailwind base;
119
+ @tailwind components;
120
+ @tailwind utilities;
121
+ ```
122
+
123
+ To the following lines:
124
+
125
+ ```css
126
+ @import "tailwindcss/base";
127
+ @import "tailwindcss/components";
128
+ @import "tailwindcss/utilities";
129
+ ```
130
+
131
+ Unless this is done, `postcss-import` doesn't work correctly.
132
+
133
+ ### Add Themify Icons, jQuery (for now) and trix editor support
134
+
135
+ Note: jQuery is needed for some of our components, but defining `window.$` won't be required soon. See PR https://github.com/bullet-train-co/bullet_train-core/pull/765
136
+
137
+ ```
138
+ yarn add @icon/themify-icons jquery
139
+ ```
140
+
141
+ To your `application.js`, add the following line:
142
+
143
+ ```js
144
+ import jquery from "jquery"
145
+ window.jQuery = jquery
146
+ window.$ = jquery
147
+
148
+ require("@icon/themify-icons/themify-icons.css")
149
+
150
+ import { trixEditor } from "@bullet-train/fields"
151
+ trixEditor()
152
+ ```
153
+
154
+ ### Add Locale Strings
155
+
156
+ Add these to your `config/locales/en.yml` under `en:`
157
+
158
+ ```yml
159
+ date:
160
+ formats:
161
+ date_field: "%m/%d/%Y"
162
+ date_and_time_field: "%m/%d/%Y %l:%M %p"
163
+ date_controller: "MM/DD/YYYY"
164
+ time:
165
+ am: AM
166
+ pm: PM
167
+ formats:
168
+ date_field: "%m/%d/%Y"
169
+ date_and_time_field: "%m/%d/%Y %l:%M %p"
170
+ date_controller: "MM/DD/YYYY h:mm A"
171
+ daterangepicker:
172
+ firstDay: 1
173
+ separator: " - "
174
+ applyLabel: "Apply"
175
+ cancelLabel: "Cancel"
176
+ fromLabel: "From"
177
+ toLabel: "To"
178
+ customRangeLabel: "Custom"
179
+ weekLabel: "W"
180
+ daysOfWeek:
181
+ - "Su"
182
+ - "Mo"
183
+ - "Tu"
184
+ - "We"
185
+ - "Th"
186
+ - "Fr"
187
+ - "Sa"
188
+ monthNames:
189
+ - "January"
190
+ - "February"
191
+ - "March"
192
+ - "April"
193
+ - "May"
194
+ - "June"
195
+ - "July"
196
+ - "August"
197
+ - "September"
198
+ - "October"
199
+ - "November"
200
+ - "December"
201
+ date_range_controller:
202
+ today: Today
203
+ yesterday: yesterday
204
+ last7Days: Last 7 Days
205
+ last30Days: Last 30 Days
206
+ thisMonth: This Month
207
+ lastMonth: Last Month
208
+ global:
209
+ buttons:
210
+ other: Other
211
+ cancel: Cancel
212
+ bulk_select:
213
+ all: All
214
+ ```
215
+
216
+ ## 2. Optional Configurations for switching colors, theme gems
217
+
218
+ ### For Setting the Active Color
219
+
220
+ ```
221
+ curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train/main/initializers/theme.rb" -o initializers/theme.rb
222
+ ```
223
+
224
+ Add the following classes to your `html` tag for your layout:
225
+
226
+ ```erb
227
+ <html class="theme-<%= BulletTrain::Themes::Light.color %> <%= "theme-secondary-#{BulletTrain::Themes::Light.secondary_color}" if BulletTrain::Themes::Light.secondary_color %>"
228
+ ```
229
+
230
+ ### For Switching Between Installed Themes
231
+
232
+ If you'd like to create your own theme but would still like to build on top of `:light`, you'll need to have both gems installed and you'll be able to switch the current theme this way.
233
+
234
+ Define `current_theme` in `app/helpers/application_helper.rb`
235
+
236
+ ```
237
+ module ApplicationHelper
238
+ def current_theme
239
+ :light
240
+ end
241
+ end
242
+ ```
243
+
244
+ To change to use a different theme:
245
+
246
+ 1. Change the value returned by `current_theme` to the new theme name
247
+ 2. Change the name of the `THEME` env var defined in `build` and `build:css` in `package.json`
248
+ 3. Change the name of the theme in the `javascript_include_tag` in the `<head>`.
249
+
250
+ ## 3. Using Locales for fields on new models
251
+
252
+ The theme's field partials work best with locale strings that are defined for the model you're creating.
253
+
254
+ Example: you've created a Project model. Here we'll create a `projects.en.yml`
255
+
256
+ 1. Run `curl -L "https://raw.githubusercontent.com/bullet-train-co/bullet_train-core/main/bullet_train-super_scaffolding/config/locales/en/scaffolding/completely_concrete/tangible_things.en.yml" -o config/locales/projects.en.yml`
257
+ 2. Search and replace `projects.en.yml` for `scaffolding/completely_concrete/tangible_things`, `Tangible Things`, `Tangible Thing`, `tangible_things` and `tangible_thing`. Replace with `projects`, `Projects`, `Project`, `projects` and `project` respectively.
258
+ 3. Remove strings you won't be using. In particular, look for comments with "skip" or "scaffolding".
259
+
260
+ Some fields use locale strings to drive their `options`. In the `tangible_things.en.yml` template file, look for `super_select_value`, `multiple_option_values` and others.
261
+
262
+ You'll notice `&` and `*` symbols prefixing some special keys in the `yml` file. Those are anchors and aliases and they help you reduce repetition in your locale strings.
263
+
264
+ To learn more about how these locales are generated in Bullet Train, see the documentation on [Bullet Train's Super Scaffolding](/docs/super-scaffolding.md)
265
+
266
+ ## 4. Partials that require special instructions, exclusions
267
+
268
+ ### For using boolean-type fields (options, buttons)
269
+
270
+ In `ApplicationController`, add this:
271
+
272
+ ```ruby
273
+ include Fields::ControllerSupport
274
+ ```
275
+
276
+ ### For the file_field partial
277
+
278
+ ```ruby
279
+ # in the model
280
+ has_one_attached :file_field_value
281
+ after_validation :remove_file_field_value, if: :file_field_value_removal?
282
+ attr_accessor :file_field_value_removal
283
+ def file_field_value_removal?
284
+ def remove_file_field_value
285
+ ```
286
+
287
+ ```ruby
288
+ # in the controller's strong_params
289
+ :file_field_value,
290
+ :file_field_value_removal,
291
+ ```
292
+
293
+ ### For `image`, `active_storage_image`
294
+
295
+ See [`account/users_helper` in BT core repo](https://github.com/bullet-train-co/bullet_train-core/blob/main/bullet_train/app/helpers/account/users_helper.rb) for implementing `photo_url_for_active_storage_attachment`
296
+
297
+ ## 5. Modifying ejected partials
298
+
299
+ ### For ejecting a theme partial and modifying it
300
+
301
+ We recommend firing up a Bullet-Train project and using its `bin/resolve` (see docs on [Indirection](indirection)) to get a copy of the partial field locally to modify.
data/docs/themes.md CHANGED
@@ -79,3 +79,8 @@ This allows the theme engine to resolve which theme in the inheritance chain wil
79
79
  ### Let your designer name their theme.
80
80
 
81
81
  You're going to have to call your theme something and there are practical reasons to not call it something generic. If you're pursuing a heavily customized design, consider allowing the designer or designers who are creating the look-and-feel of your application to name their own masterpiece. Giving it a distinct name will really help differentiate things when you're ready to start introducing additional facets to your application or a totally new look-and-feel down the road.
82
+
83
+ ## Additional Themes Documentation
84
+
85
+ * [Installing Bullet-Train Themes on Other Rails Projects](/docs/themes/on-other-rails-projects.md)
86
+ * [Installing Bullet-Train Themes on Jumpstart PRO Projects](/docs/themes/on-jumpstart-pro-projects.md)
@@ -1,3 +1,3 @@
1
1
  module BulletTrain
2
- VERSION = "1.6.30"
2
+ VERSION = "1.6.31"
3
3
  end
@@ -1,32 +1,5 @@
1
1
  require "io/wait"
2
2
 
3
- namespace :bt do
4
- desc "Symlink registered gems in `./tmp/gems` so their views, etc. can be inspected by Tailwind CSS."
5
- task link: :environment do
6
- if Dir.exist?("tmp/gems")
7
- puts "Removing previously linked gems."
8
- `rm -f tmp/gems/*`
9
- else
10
- if File.exist?("tmp/gems")
11
- raise "A file named `tmp/gems` already exists? It has to be removed before we can create the required directory."
12
- end
13
-
14
- puts "Creating 'tmp/gems' directory."
15
- `mkdir tmp/gems`
16
- end
17
-
18
- `touch tmp/gems/.keep`
19
-
20
- BulletTrain.linked_gems.each do |linked_gem|
21
- target = `bundle show #{linked_gem}`.chomp
22
- if target.present?
23
- puts "Linking '#{linked_gem}' to '#{target}'."
24
- `ln -s #{target} tmp/gems/#{linked_gem}`
25
- end
26
- end
27
- end
28
- end
29
-
30
3
  namespace :bullet_train do
31
4
  desc "Figure out where something is coming from."
32
5
  task :resolve, [:all_options] => :environment do |t, arguments|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.30
4
+ version: 1.6.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-07 00:00:00.000000000 Z
11
+ date: 2024-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard
@@ -539,8 +539,6 @@ files:
539
539
  - app/controllers/registrations_controller.rb
540
540
  - app/controllers/sessions_controller.rb
541
541
  - app/helpers/account/buttons_helper.rb
542
- - app/helpers/account/dates_helper.rb
543
- - app/helpers/account/forms_helper.rb
544
542
  - app/helpers/account/invitations_helper.rb
545
543
  - app/helpers/account/locale_helper.rb
546
544
  - app/helpers/account/markdown_helper.rb
@@ -549,11 +547,9 @@ files:
549
547
  - app/helpers/account/role_helper.rb
550
548
  - app/helpers/account/teams_helper.rb
551
549
  - app/helpers/account/users_helper.rb
552
- - app/helpers/attributes_helper.rb
553
550
  - app/helpers/base_helper.rb
554
551
  - app/helpers/concerns/helpers/base.rb
555
552
  - app/helpers/email_helper.rb
556
- - app/helpers/images_helper.rb
557
553
  - app/helpers/invitation_only_helper.rb
558
554
  - app/helpers/invitations_helper.rb
559
555
  - app/javascript/controllers/bulk_action_form_controller.js
@@ -757,6 +753,8 @@ files:
757
753
  - docs/teams.md
758
754
  - docs/testing.md
759
755
  - docs/themes.md
756
+ - docs/themes/on-jumpstart-pro-projects.md
757
+ - docs/themes/on-other-rails-projects.md
760
758
  - docs/trademark.md
761
759
  - docs/tunneling.md
762
760
  - docs/upgrades.md
@@ -1,70 +0,0 @@
1
- module Account::DatesHelper
2
- def display_date(timestamp, custom_date_format = nil, format: :default, date_format: nil)
3
- return nil unless timestamp
4
- format = date_format if date_format
5
-
6
- if format && format == :default
7
- # e.g. October 11, 2018
8
- if custom_date_format
9
- local_time(timestamp).strftime(custom_date_format)
10
- elsif local_time(timestamp).year == local_time(Time.now).year
11
- local_time(timestamp).strftime("%B %-d")
12
- else
13
- local_time(timestamp).strftime("%B %-d, %Y")
14
- end
15
- else
16
- localize(local_time(timestamp).to_date, format: format)
17
- end
18
- end
19
-
20
- def display_time(timestamp, custom_time_format = nil, format: :default, time_format: nil)
21
- return nil unless timestamp
22
- format = time_format if time_format
23
-
24
- if format && format == :default
25
- # e.g. 4:22 PM
26
- local_time(timestamp).strftime(custom_time_format || "%l:%M %p")
27
- else
28
- localize(local_time(timestamp).to_time, format: format)
29
- end
30
- end
31
-
32
- def display_date_and_time(timestamp, custom_date_format = nil, custom_time_format = nil, format: :default, date_format: nil, time_format: nil)
33
- return nil unless timestamp
34
- format = "#{date_format} #{time_format}" if date_format && time_format
35
-
36
- if format && format == :default
37
- # e.g. Today at 4:22 PM
38
- # e.g. Yesterday at 2:12 PM
39
- # e.g. April 24 at 7:39 AM
40
- # today?
41
- if local_time(timestamp).to_date == local_time(Time.now).to_date
42
- "Today at #{display_time(timestamp, custom_time_format)}"
43
- # yesterday?
44
- elsif (local_time(timestamp).to_date) == (local_time(Time.now).to_date - 1.day)
45
- "Yesterday at #{display_time(timestamp, custom_time_format)}"
46
- else
47
- "#{display_date(timestamp, custom_date_format)} at #{display_time(timestamp, custom_time_format)}"
48
- end
49
- else
50
- localize(local_time(timestamp).to_datetime, format: format)
51
- end
52
- end
53
-
54
- def local_time(timestamp)
55
- timestamp&.in_time_zone(current_user.time_zone)
56
- end
57
-
58
- def am_pm?
59
- !"#{I18n.t("time.am", fallback: false, default: "")}#{I18n.t("time.pm", fallback: false, default: "")}".empty?
60
- end
61
-
62
- def time_zone_name_to_id
63
- ActiveSupport::TimeZone.all.map { |tz| {tz.name.to_s => tz.tzinfo.name} }.reduce({}, :merge)
64
- end
65
-
66
- def current_time_zone
67
- current_time_zone_name = current_user&.time_zone || current_user&.current_team&.time_zone || "UTC"
68
- ActiveSupport::TimeZone.find_tzinfo(current_time_zone_name).name
69
- end
70
- end
@@ -1,65 +0,0 @@
1
- module Account::FormsHelper
2
- PRESENCE_VALIDATORS = [ActiveRecord::Validations::PresenceValidator, ActiveModel::Validations::PresenceValidator]
3
-
4
- def presence_validated?(object, attribute)
5
- validators = object.class.validators
6
- validators.select! do |validator|
7
- PRESENCE_VALIDATORS.include?(validator.class) && validator.attributes.include?(attribute)
8
- end
9
- validators.any?
10
- end
11
-
12
- def flush_content_for(name)
13
- content_for name, flush: true do
14
- ""
15
- end
16
- end
17
-
18
- def options_with_labels(options, namespace)
19
- hash = {}
20
- options.each do |option|
21
- hash[option] = t([namespace, option].join("."))
22
- end
23
- hash
24
- end
25
-
26
- def if_present(string)
27
- string.present? ? string : nil
28
- end
29
-
30
- def model_key(form)
31
- form.object.class.name.pluralize.underscore
32
- end
33
-
34
- def labels_for(form, method)
35
- keys = [:placeholder, :label, :help, :options_help]
36
- path = [model_key(form), (current_fields_namespace || :fields), method].compact
37
- Struct.new(*keys).new(*keys.map { |key| t((path + [key]).join("."), default: "").presence })
38
- end
39
-
40
- def options_for(form, method)
41
- # e.g. "scaffolding/completely_concrete/tangible_things.fields.text_area_value.options"
42
- path = [model_key(form), (current_fields_namespace || :fields), method, :options]
43
- options = t(path.compact.join("."))
44
- return options unless options.is_a?(Hash)
45
- options.stringify_keys
46
- end
47
-
48
- def legacy_label_for(form, method)
49
- # e.g. 'scaffolding/things.labels.name'
50
- key = "#{model_key(form)}.labels.#{method}"
51
- # e.g. 'scaffolding/things.labels.name' or 'scaffolding.things.labels.name' or nil
52
- t(key, default: "").presence || t(key.tr("/", "."), default: "").presence
53
- end
54
-
55
- def within_fields_namespace(namespace)
56
- @fields_namespaces ||= []
57
- @fields_namespaces << namespace
58
- yield
59
- @fields_namespaces.pop
60
- end
61
-
62
- def current_fields_namespace
63
- @fields_namespaces&.last
64
- end
65
- end
@@ -1,17 +0,0 @@
1
- module AttributesHelper
2
- def current_attributes_object
3
- @_current_attribute_settings&.dig(:object)
4
- end
5
-
6
- def current_attributes_strategy
7
- @_current_attribute_settings&.dig(:strategy)
8
- end
9
-
10
- def with_attribute_settings(object: current_attributes_object, strategy: current_attributes_strategy)
11
- old_attribute_settings = @_current_attribute_settings
12
- @_current_attribute_settings = {object: object, strategy: strategy}
13
- yield
14
- ensure
15
- @_current_attribute_settings = old_attribute_settings
16
- end
17
- end
@@ -1,7 +0,0 @@
1
- module ImagesHelper
2
- def image_width_for_height(filename, target_height)
3
- source_width, source_height = FastImage.size("#{Rails.root}/app/assets/images/#{filename}")
4
- ratio = source_width.to_f / source_height.to_f
5
- (target_height * ratio).to_i
6
- end
7
- end