bullet_train 1.1.7 → 1.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/account/teams/controller_base.rb +4 -1
- data/app/controllers/concerns/documentation_support.rb +2 -2
- data/app/javascript/controllers/index.js +2 -0
- data/app/javascript/controllers/select_all_controller.js +82 -0
- data/app/views/public/home/docs.html.erb +2 -2
- data/config/locales/en/framework_packages.yml +13 -17
- data/docs/billing/usage.md +148 -0
- data/lib/bullet_train/version.rb +1 -1
- data/lib/colorizer.rb +1 -1
- data/lib/tasks/bullet_train_tasks.rake +15 -11
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 861c6f60ec10ff83389d2ac53d5a702dd230db869b890b6e46f84896fecb8b7b
|
4
|
+
data.tar.gz: 55d51e53583ef3e2bdd179f821e7a48920483acea55adb818a736ca411106a70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5ddb5c77373a119154c1f1fd1993b9f89723dd0239f4e71402e3c7399100f38734edbd0bb9768d2545e607d98281da486ab7ac6c2d55e3b06da902eceebc4a3
|
7
|
+
data.tar.gz: 47337cee5019ad52c09e325cb9ef035b24d59da94083337a817cc45342ea0c0feac586e115ac793b3bd802e20e1b985aecd479b603dbed2b1765dbaf2638333a
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Account::Teams::ControllerBase
|
2
2
|
extend ActiveSupport::Concern
|
3
|
+
extend Controllers::Base
|
3
4
|
|
4
5
|
included do
|
5
6
|
load_and_authorize_resource :team, class: "Team", prepend: true,
|
@@ -21,7 +22,9 @@ module Account::Teams::ControllerBase
|
|
21
22
|
|
22
23
|
private
|
23
24
|
|
24
|
-
|
25
|
+
if defined?(Api::V1::ApplicationController)
|
26
|
+
include strong_parameters_from_api
|
27
|
+
end
|
25
28
|
end
|
26
29
|
|
27
30
|
# GET /teams
|
@@ -3,8 +3,8 @@ module DocumentationSupport
|
|
3
3
|
|
4
4
|
def docs
|
5
5
|
target = params[:page].presence || "index"
|
6
|
-
|
7
|
-
@
|
6
|
+
all_paths = ([Rails.root.to_s] + `bundle show --paths`.lines.map(&:chomp))
|
7
|
+
@path = all_paths.map { |path| path + "/docs/#{target}.md" }.detect { |path| File.exist?(path) }
|
8
8
|
render :docs, layout: "docs"
|
9
9
|
end
|
10
10
|
end
|
@@ -6,6 +6,7 @@ import ClipboardController from './clipboard_controller'
|
|
6
6
|
import FormController from './form_controller'
|
7
7
|
import MobileMenuController from './mobile_menu_controller'
|
8
8
|
import TextToggleController from './text_toggle_controller'
|
9
|
+
import SelectAllController from './select_all_controller'
|
9
10
|
|
10
11
|
export const controllerDefinitions = [
|
11
12
|
[BulkActionFormController, 'bulk_action_form_controller.js'],
|
@@ -14,6 +15,7 @@ export const controllerDefinitions = [
|
|
14
15
|
[FormController, 'form_controller.js'],
|
15
16
|
[MobileMenuController, 'mobile_menu_controller.js'],
|
16
17
|
[TextToggleController, 'text_toggle_controller.js'],
|
18
|
+
[SelectAllController, 'select_all_controller.js'],
|
17
19
|
].map(function(d) {
|
18
20
|
const key = d[1]
|
19
21
|
const controller = d[0]
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = [ "checkbox", "toggleCheckbox", "toggleLabel", "wrapper" ]
|
5
|
+
static classes = [ "unavailable" ]
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
this.enableSelectAll()
|
9
|
+
}
|
10
|
+
|
11
|
+
enableSelectAll() {
|
12
|
+
if (!this.hasWrapperTarget) { return }
|
13
|
+
if (!this.hasUnavailableClass) { return }
|
14
|
+
|
15
|
+
this.wrapperTarget.classList.remove(this.unavailableClass)
|
16
|
+
this.updateToggle()
|
17
|
+
}
|
18
|
+
|
19
|
+
selectAllOrNone(event) {
|
20
|
+
event.preventDefault()
|
21
|
+
event.stopPropagation()
|
22
|
+
if (this.allSelected) {
|
23
|
+
this.selectNone()
|
24
|
+
} else {
|
25
|
+
this.selectAll()
|
26
|
+
}
|
27
|
+
this.updateToggle()
|
28
|
+
this.dispatch('toggled')
|
29
|
+
}
|
30
|
+
|
31
|
+
selectAll() {
|
32
|
+
this.checkboxTargets.forEach(checkbox => {
|
33
|
+
checkbox.checked = true
|
34
|
+
})
|
35
|
+
}
|
36
|
+
|
37
|
+
selectNone() {
|
38
|
+
this.checkboxTargets.forEach(checkbox => {
|
39
|
+
checkbox.checked = false
|
40
|
+
})
|
41
|
+
}
|
42
|
+
|
43
|
+
updateToggle() {
|
44
|
+
let checkbox = this.toggleCheckboxTarget
|
45
|
+
let useAlternateLabel = false
|
46
|
+
|
47
|
+
if (this.allSelected) {
|
48
|
+
if (checkbox) {
|
49
|
+
checkbox.checked = true
|
50
|
+
checkbox.indeterminate = false
|
51
|
+
}
|
52
|
+
useAlternateLabel = true
|
53
|
+
} else if (this.selectedValues.length > 0) {
|
54
|
+
if (checkbox) {
|
55
|
+
checkbox.indeterminate = true
|
56
|
+
}
|
57
|
+
} else {
|
58
|
+
if (checkbox) {
|
59
|
+
checkbox.checked = false
|
60
|
+
checkbox.indeterminate = false
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
if (this.hasToggleLabelTarget) {
|
65
|
+
this.toggleLabelTarget.dispatchEvent(new CustomEvent(`${this.identifier}:toggle-select-all-label`, { detail: { useAlternate: useAlternateLabel }} ))
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
get selectedValues() {
|
70
|
+
let values = []
|
71
|
+
this.checkboxTargets.forEach(checkbox => {
|
72
|
+
if (checkbox.checked) {
|
73
|
+
values.push(checkbox.value)
|
74
|
+
}
|
75
|
+
})
|
76
|
+
return values
|
77
|
+
}
|
78
|
+
|
79
|
+
get allSelected() {
|
80
|
+
return this.selectedValues.length === this.checkboxTargets.length
|
81
|
+
}
|
82
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
|
-
<% @body = markdown(File.read(
|
1
|
+
<% @body = markdown(File.read(@path).gsub('.md)', ')')) %>
|
2
2
|
|
3
|
-
<% if @
|
3
|
+
<% if @path.include?("docs/index.md") %>
|
4
4
|
<% header, groups = @body.split("<h2>", 2) %>
|
5
5
|
<%= header.html_safe %>
|
6
6
|
|
@@ -6,38 +6,34 @@ en:
|
|
6
6
|
bullet_train-api:
|
7
7
|
git: "bullet-train-co/bullet_train-api"
|
8
8
|
bullet_train-fields:
|
9
|
-
git: "bullet-train-co/bullet_train-
|
9
|
+
git: "bullet-train-co/bullet_train-core"
|
10
10
|
npm: "@bullet-train/fields"
|
11
11
|
bullet_train-has_uuid:
|
12
|
-
git: "bullet-train-co/bullet_train-
|
12
|
+
git: "bullet-train-co/bullet_train-core"
|
13
13
|
bullet_train-incoming_webhooks:
|
14
|
-
git: "bullet-train-co/bullet_train-
|
14
|
+
git: "bullet-train-co/bullet_train-core"
|
15
15
|
bullet_train-integrations:
|
16
|
-
git: "bullet-train-co/bullet_train-
|
16
|
+
git: "bullet-train-co/bullet_train-core"
|
17
17
|
bullet_train-integrations-stripe:
|
18
|
-
git: "bullet-train-co/bullet_train-
|
18
|
+
git: "bullet-train-co/bullet_train-core"
|
19
19
|
bullet_train-obfuscates_id:
|
20
|
-
git: "bullet-train-co/bullet_train-
|
20
|
+
git: "bullet-train-co/bullet_train-core"
|
21
21
|
bullet_train-outgoing_webhooks:
|
22
22
|
git: "bullet-train-co/bullet_train-outgoing_webhooks"
|
23
|
-
bullet_train-outgoing_webhooks-core:
|
24
|
-
git: "bullet-train-co/bullet_train-outgoing_webhooks-core"
|
25
23
|
bullet_train-scope_questions:
|
26
|
-
git: "bullet-train-co/bullet_train-
|
24
|
+
git: "bullet-train-co/bullet_train-core"
|
27
25
|
bullet_train-scope_validator:
|
28
|
-
git: "bullet-train-co/bullet_train-
|
26
|
+
git: "bullet-train-co/bullet_train-core"
|
29
27
|
bullet_train-sortable:
|
30
|
-
git: "bullet-train-co/bullet_train-
|
28
|
+
git: "bullet-train-co/bullet_train-core"
|
31
29
|
npm: "@bullet-train/bullet-train-sortable"
|
32
30
|
bullet_train-super_scaffolding:
|
33
31
|
git: "bullet-train-co/bullet_train-super_scaffolding"
|
34
32
|
bullet_train-super_load_and_authorize_resource:
|
35
|
-
git: "bullet-train-co/bullet_train-
|
33
|
+
git: "bullet-train-co/bullet_train-core"
|
36
34
|
bullet_train-themes:
|
37
|
-
git: "bullet-train-co/bullet_train-
|
38
|
-
bullet_train-themes-base:
|
39
|
-
git: "bullet-train-co/bullet_train-themes-base"
|
35
|
+
git: "bullet-train-co/bullet_train-core"
|
40
36
|
bullet_train-themes-light:
|
41
|
-
git: "bullet-train-co/bullet_train-
|
37
|
+
git: "bullet-train-co/bullet_train-core"
|
42
38
|
bullet_train-themes-tailwind_css:
|
43
|
-
git: "bullet-train-co/bullet_train-
|
39
|
+
git: "bullet-train-co/bullet_train-core"
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Bullet Train Usage Limits
|
2
|
+
|
3
|
+
Bullet Train provides a holistic method for defining model-based usage limits in your Rails application.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
### 1. Purchase Bullet Train Pro
|
8
|
+
|
9
|
+
First, [purchase Bullet Train Pro](https://buy.stripe.com/aEU7vc4dBfHtfO89AV). Once you've completed this process, you'll be issued a private token for the Bullet Train Pro package server. The process is currently completed manually, so you may have to way a little to receive your keys.
|
10
|
+
|
11
|
+
### 2. Install the Package
|
12
|
+
|
13
|
+
### 2.1. Add the Private Ruby Gems
|
14
|
+
|
15
|
+
You'll need to specify both Ruby gems in your `Gemfile`, since we have to specify a private source for both:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
source "https://YOUR_TOKEN_HERE@gem.fury.io/bullettrain" do
|
19
|
+
gem "bullet_train-billing"
|
20
|
+
gem "bullet_train-billing-stripe" # Or whichever billing provider you're using.
|
21
|
+
gem "bullet_train-billing-usage"
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
### 2.2. Bundle Install
|
26
|
+
|
27
|
+
```
|
28
|
+
bundle install
|
29
|
+
```
|
30
|
+
|
31
|
+
### 2.3. Copy Database Migrations
|
32
|
+
|
33
|
+
Use the following two commands on your shell to copy the required migrations into your local project:
|
34
|
+
|
35
|
+
```
|
36
|
+
cp `bundle show --paths | grep bullet_train-billing | sort | head -n 1`/db/migrate/* db/migrate
|
37
|
+
cp `bundle show --paths | grep bullet_train-billing-stripe | sort | head -n 1`/db/migrate/* db/migrate
|
38
|
+
```
|
39
|
+
|
40
|
+
Note this is different than how many Rails engines ask you to install migrations. This is intentional, as we want to maintain the original timestamps associated with these migrations.
|
41
|
+
|
42
|
+
### 2.4. Run Migrations
|
43
|
+
|
44
|
+
```
|
45
|
+
rake db:migrate
|
46
|
+
```
|
47
|
+
|
48
|
+
## Configuration
|
49
|
+
Usage limit configuration piggybacks on your [product definitions](/docs/billing/stripe.md) in `config/models/billing/products.yml`. It may help to make reference to the [default product definitions in the Bullet Train starter repository](https://github.com/bullet-train-co/bullet_train/blob/main/config/models/billing/products.yml).
|
50
|
+
|
51
|
+
## Basic Usage Limits
|
52
|
+
All limit definitions are organized by product, then by model, and finally by _verb_. For example, you can define the number of projects a team is allowed to have on a basic plan like so:
|
53
|
+
|
54
|
+
```yaml
|
55
|
+
basic:
|
56
|
+
prices:
|
57
|
+
# ...
|
58
|
+
limits:
|
59
|
+
projects:
|
60
|
+
have:
|
61
|
+
count: 3
|
62
|
+
enforcement: hard
|
63
|
+
upgradable: true
|
64
|
+
```
|
65
|
+
|
66
|
+
It's important to note that `have` is a special verb and represents the simple `count` of a given model on a `Team`. All _other_ verbs will be interpreted as time-based usage limits.
|
67
|
+
|
68
|
+
### Options
|
69
|
+
- `enforcement` can be `hard` or `soft`.
|
70
|
+
- When a `hard` limit is hit, the create form will be disabled.
|
71
|
+
- When a `soft` limit is hit, users are simply notified, but can continue to surpass the limit.
|
72
|
+
- `upgradable` indicates whether or not a user should be prompted to upgrade when they hit this limit.
|
73
|
+
|
74
|
+
### Excluding Records from `have` Usage Limits
|
75
|
+
All models have an overridable `billable` scope that includes all records by default. You can override this scope to ensure that certain records are filtered out from consideration when calculating usage limits. For example, we do the following on `Membership` to exclude removed team members from contributing to any limitation put on the number of team members, like so:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
scope :billable, -> { current_and_invited }
|
79
|
+
```
|
80
|
+
|
81
|
+
## Time-Based Usage Limits
|
82
|
+
|
83
|
+
### Configuring Limits
|
84
|
+
In addition to simple `have` usage limits, you can specify other types of usage limits by defining other verbs. For example, you can limit the number of blog posts that can be published in a 3-day period on the free plan like this:
|
85
|
+
|
86
|
+
```yaml
|
87
|
+
free:
|
88
|
+
limits:
|
89
|
+
blogs/posts:
|
90
|
+
publish:
|
91
|
+
count: 1
|
92
|
+
duration: 3
|
93
|
+
interval: days
|
94
|
+
enforcement: hard
|
95
|
+
```
|
96
|
+
|
97
|
+
- `count` is how many times something can happen.
|
98
|
+
- `duration` and `interval` represent the time period we'll track for, e.g. "3 days" in this case.
|
99
|
+
- Valid options for `interval` are anything you can append to an integer, e.g. `minutes`, `hours`, `days`, `weeks`, `months`, etc., both plural and singular.
|
100
|
+
|
101
|
+
### Tracking Usage
|
102
|
+
For these custom verbs, it's important to also instrument the application for tracking when these actions have taken place. For example:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
class Blogs::Post < ApplicationRecord
|
106
|
+
# ...
|
107
|
+
|
108
|
+
def publish!
|
109
|
+
update(published_at: Time.zone.now)
|
110
|
+
track_billing_usage(:published)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
If you'd like to increment the usage count by more than one, you can pass a quantity like `count: 5` to this call.
|
116
|
+
|
117
|
+
### Cycling Trackers Regularly
|
118
|
+
We include a Rake task you'll need to run on a regular basis in order to cycle the usage trackers that are created at a `Team` level. By default, you should probably run this every five minutes:
|
119
|
+
|
120
|
+
```
|
121
|
+
rake billing:cycle_usage_trackers
|
122
|
+
```
|
123
|
+
|
124
|
+
## Checking Usage Limits
|
125
|
+
|
126
|
+
### Checking Basic Limits
|
127
|
+
For basic `have` limits, forms generated by Super Scaffolding will be automatically disabled when a `hard` limit has been hit. Index views will also alert users to a limit being hit or broken for both `hard` and `soft` limits.
|
128
|
+
|
129
|
+
> If your Bullet Train application scaffolding predates this feature, you can reference the newest Tangible Things [index template](https://github.com/bullet-train-co/bullet_train-super_scaffolding/blob/main/app/views/account/scaffolding/completely_concrete/tangible_things/_index.html.erb) and [form template](https://github.com/bullet-train-co/bullet_train-super_scaffolding/blob/main/app/views/account/scaffolding/completely_concrete/tangible_things/_form.html.erb) to see how we're using the `shared/limits/index` and `shared/limits/form` partials to present and enforce usage limits, and copy this usage in your own views.
|
130
|
+
|
131
|
+
### Checking Time-Based Limits
|
132
|
+
To make decisions based on or enforce time-based limits in your views and controllers, you can use the `current_limits` helper like this:
|
133
|
+
|
134
|
+
```
|
135
|
+
current_limits.can?(:publish, Blogs::Post)
|
136
|
+
```
|
137
|
+
|
138
|
+
(You can also pass quantities like `count: 5` as an option.)
|
139
|
+
|
140
|
+
#### Presenting an Error
|
141
|
+
|
142
|
+
If you're checking on this in a controller before taking an action and you want to present an error to the user based on their usage, you can redirect with this special flash error message key:
|
143
|
+
|
144
|
+
```
|
145
|
+
flash[:error] = :create_limit
|
146
|
+
redirect_to [:account, @post]
|
147
|
+
```
|
148
|
+
> TODO This technically works but needs to be redone. Too limited.
|
data/lib/bullet_train/version.rb
CHANGED
data/lib/colorizer.rb
CHANGED
@@ -97,17 +97,18 @@ namespace :bullet_train do
|
|
97
97
|
|
98
98
|
if gem
|
99
99
|
details = framework_packages[gem]
|
100
|
+
package = details[:git].split("/").last
|
100
101
|
|
101
102
|
puts "OK! Let's work on `#{gem}` together!".green
|
102
103
|
puts ""
|
103
104
|
|
104
|
-
if File.exist?("local/#{
|
105
|
-
puts "We found the repository in `local/#{
|
105
|
+
if File.exist?("local/#{package}")
|
106
|
+
puts "We found the repository in `local/#{package}`. We will try to use what's already there.".yellow
|
106
107
|
puts ""
|
107
108
|
|
108
109
|
# Adding these flags enables us to execute git commands in the gem from our starter repo.
|
109
|
-
work_tree_flag = "--work-tree=local/#{
|
110
|
-
git_dir_flag = "--git-dir=local/#{
|
110
|
+
work_tree_flag = "--work-tree=local/#{package}"
|
111
|
+
git_dir_flag = "--git-dir=local/#{package}/.git"
|
111
112
|
|
112
113
|
git_status = `git #{work_tree_flag} #{git_dir_flag} status`
|
113
114
|
unless git_status.match?("nothing to commit, working tree clean")
|
@@ -119,7 +120,7 @@ namespace :bullet_train do
|
|
119
120
|
current_branch = `git #{work_tree_flag} #{git_dir_flag} branch`.split("\n").select { |branch_name| branch_name.match?(/^\*\s/) }.pop.gsub(/^\*\s/, "")
|
120
121
|
unless current_branch == "main"
|
121
122
|
puts "Previously on #{current_branch}.".blue
|
122
|
-
puts "Switching local/#{
|
123
|
+
puts "Switching local/#{package} to main branch.".blue
|
123
124
|
stream("git #{work_tree_flag} #{git_dir_flag} checkout main")
|
124
125
|
end
|
125
126
|
|
@@ -127,7 +128,7 @@ namespace :bullet_train do
|
|
127
128
|
stream("git #{work_tree_flag} #{git_dir_flag} pull origin main")
|
128
129
|
else
|
129
130
|
# Use https:// URLs when using this task in Gitpod.
|
130
|
-
stream "git clone #{`whoami`.chomp == "gitpod" ? "https://github.com/" : "git@github.com:"}#{details[:git]}.git local/#{
|
131
|
+
stream "git clone #{(`whoami`.chomp == "gitpod") ? "https://github.com/" : "git@github.com:"}#{details[:git]}.git local/#{package}"
|
131
132
|
end
|
132
133
|
|
133
134
|
stream("git #{work_tree_flag} #{git_dir_flag} fetch")
|
@@ -141,24 +142,27 @@ namespace :bullet_train do
|
|
141
142
|
stream("git #{work_tree_flag} #{git_dir_flag} checkout #{input}")
|
142
143
|
end
|
143
144
|
|
145
|
+
glob = if package == "bullet_train-core"
|
146
|
+
", glob: \"#{gem}/#{gem}.gemspec\""
|
147
|
+
end
|
148
|
+
|
144
149
|
puts ""
|
145
150
|
puts "Now we'll try to link up that repository in the `Gemfile`.".blue
|
146
|
-
if `cat Gemfile | grep "gem \\\"#{gem}\\\", path: \\\"local/#{
|
151
|
+
if `cat Gemfile | grep "gem \\\"#{gem}\\\", path: \\\"local/#{package}\\\""`.chomp.present?
|
147
152
|
puts "This gem is already linked to a checked out copy in `local` in the `Gemfile`.".green
|
148
153
|
elsif `cat Gemfile | grep "gem \\\"#{gem}\\\","`.chomp.present?
|
149
154
|
puts "This gem already has some sort of alternative source configured in the `Gemfile`.".yellow
|
150
155
|
puts "We can't do anything with this. Sorry! We'll proceed, but you have to link this package yourself.".red
|
151
156
|
elsif `cat Gemfile | grep "gem \\\"#{gem}\\\""`.chomp.present?
|
152
157
|
puts "This gem is directly present in the `Gemfile`, so we'll update that line.".green
|
153
|
-
|
154
158
|
text = File.read("Gemfile")
|
155
|
-
new_contents = text.gsub(/gem "#{gem}"/, "gem \"#{gem}\", path: \"local/#{
|
159
|
+
new_contents = text.gsub(/gem "#{gem}"/, "gem \"#{gem}\", path: \"local/#{package}\"#{glob}")
|
156
160
|
File.open("Gemfile", "w") { |file| file.puts new_contents }
|
157
161
|
else
|
158
162
|
puts "This gem isn't directly present in the `Gemfile`, so we'll add it temporarily.".green
|
159
163
|
File.open("Gemfile", "a+") { |file|
|
160
164
|
file.puts
|
161
|
-
file.puts "gem \"#{gem}\", path: \"local/#{
|
165
|
+
file.puts "gem \"#{gem}\", path: \"local/#{package}\"#{glob} # Added by `bin/develop`."
|
162
166
|
}
|
163
167
|
end
|
164
168
|
|
@@ -172,7 +176,7 @@ namespace :bullet_train do
|
|
172
176
|
|
173
177
|
puts ""
|
174
178
|
puts "OK, we're opening that package in your IDE, `#{ENV["IDE"] || "code"}`. (You can configure this with `export IDE=whatever`.)".blue
|
175
|
-
`#{ENV["IDE"] || "code"} local/#{
|
179
|
+
`#{ENV["IDE"] || "code"} local/#{package}`
|
176
180
|
|
177
181
|
puts ""
|
178
182
|
if details[:npm]
|
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.1.
|
4
|
+
version: 1.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: bullet_train-routes
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: devise
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -475,6 +489,7 @@ files:
|
|
475
489
|
- app/javascript/controllers/form_controller.js
|
476
490
|
- app/javascript/controllers/index.js
|
477
491
|
- app/javascript/controllers/mobile_menu_controller.js
|
492
|
+
- app/javascript/controllers/select_all_controller.js
|
478
493
|
- app/javascript/controllers/text_toggle_controller.js
|
479
494
|
- app/javascript/electron/index.js
|
480
495
|
- app/javascript/index.js
|
@@ -611,6 +626,7 @@ files:
|
|
611
626
|
- docs/action-models.md
|
612
627
|
- docs/authentication.md
|
613
628
|
- docs/billing/stripe.md
|
629
|
+
- docs/billing/usage.md
|
614
630
|
- docs/desktop.md
|
615
631
|
- docs/field-partials.md
|
616
632
|
- docs/field-partials/buttons.md
|