bullet_train 1.6.30 → 1.6.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/mailers/concerns/mailers/base.rb +1 -1
- data/docs/themes/on-jumpstart-pro-projects.md +488 -0
- data/docs/themes/on-other-rails-projects.md +301 -0
- data/docs/themes.md +5 -0
- data/lib/bullet_train/version.rb +1 -1
- data/lib/tasks/bullet_train_tasks.rake +0 -27
- metadata +4 -6
- data/app/helpers/account/dates_helper.rb +0 -70
- data/app/helpers/account/forms_helper.rb +0 -65
- data/app/helpers/attributes_helper.rb +0 -17
- data/app/helpers/images_helper.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81d723badfe7c8bf256b9c1f937cd213e67c91a455c6bda1e7006c7f0ddbec71
|
4
|
+
data.tar.gz: c3063d76a9ae3ef2e73346342a797ccfd046e8f4b9d029b772c5de4bd31ebe6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88cfc74197d49685eaa3e582c9ec35e830ce31469b9585eea07e1df5425344bf94b50722c156d962cd1d187af2ad1e053e7edd67d104472a62d1fa8154e5633d
|
7
|
+
data.tar.gz: 9c9a00cf58fa5abe325ea0a5b7bb8ade4159eec31d0af1455733f618def5b876eaf0f40f72fdbac62c53f739cc73645b249e26b467d76a0a7b11a941ea8d74f0
|
@@ -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)
|
data/lib/bullet_train/version.rb
CHANGED
@@ -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.
|
4
|
+
version: 1.6.32
|
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-
|
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
|