potassium 6.1.0 → 6.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +103 -38
- data/.circleci/setup-rubygems.sh +3 -0
- data/.gitignore +2 -1
- data/.node-version +1 -1
- data/.rubocop.yml +530 -0
- data/CHANGELOG.md +50 -1
- data/README.md +11 -3
- data/lib/potassium/assets/.circleci/config.yml.erb +107 -40
- data/lib/potassium/assets/.pryrc +0 -6
- data/lib/potassium/assets/.rubocop.yml +13 -0
- data/lib/potassium/assets/README.yml +45 -8
- data/lib/potassium/assets/active_admin/policies/admin_user_policy.rb +2 -0
- data/lib/potassium/assets/active_admin/policies/comment_policy.rb +2 -0
- data/lib/potassium/assets/active_admin/policies/default_policy.rb +49 -0
- data/lib/potassium/assets/active_admin/policies/page_policy.rb +2 -0
- data/lib/potassium/assets/app/javascript/app.spec.js +1 -1
- data/lib/potassium/assets/app/views/shared/_gtm_body.html.erb +4 -0
- data/lib/potassium/assets/app/views/shared/_gtm_head.html.erb +7 -0
- data/lib/potassium/assets/testing/.rspec +1 -0
- data/lib/potassium/assets/testing/devise_config.rb +6 -0
- data/lib/potassium/assets/testing/factory_bot_config.rb +3 -0
- data/lib/potassium/assets/testing/faker_config.rb +1 -0
- data/lib/potassium/assets/testing/power_types_config.rb +1 -0
- data/lib/potassium/assets/testing/rails_helper.rb +130 -49
- data/lib/potassium/assets/testing/shoulda_matchers_config.rb +8 -0
- data/lib/potassium/assets/testing/simplecov_config.rb +64 -0
- data/lib/potassium/assets/testing/system_tests_config.rb +6 -0
- data/lib/potassium/cli_options.rb +19 -3
- data/lib/potassium/helpers/template-helpers.rb +4 -0
- data/lib/potassium/recipes/admin.rb +27 -17
- data/lib/potassium/recipes/api.rb +2 -0
- data/lib/potassium/recipes/background_processor.rb +43 -32
- data/lib/potassium/recipes/ci.rb +9 -39
- data/lib/potassium/recipes/coverage.rb +35 -0
- data/lib/potassium/recipes/file_storage.rb +1 -1
- data/lib/potassium/recipes/front_end.rb +26 -13
- data/lib/potassium/recipes/google_tag_manager.rb +94 -0
- data/lib/potassium/recipes/heroku.rb +43 -31
- data/lib/potassium/recipes/mailer.rb +18 -5
- data/lib/potassium/recipes/monitoring.rb +5 -0
- data/lib/potassium/recipes/pundit.rb +29 -10
- data/lib/potassium/recipes/rails.rb +0 -4
- data/lib/potassium/recipes/schedule.rb +16 -1
- data/lib/potassium/recipes/spring.rb +9 -0
- data/lib/potassium/recipes/style.rb +2 -2
- data/lib/potassium/recipes/testing.rb +75 -18
- data/lib/potassium/templates/application.rb +7 -2
- data/lib/potassium/version.rb +7 -4
- data/potassium.gemspec +3 -1
- data/spec/features/background_processor_spec.rb +7 -5
- data/spec/features/ci_spec.rb +7 -4
- data/spec/features/coverage_spec.rb +26 -0
- data/spec/features/front_end_spec.rb +18 -1
- data/spec/features/google_tag_manager_spec.rb +36 -0
- data/spec/features/heroku_spec.rb +0 -4
- data/spec/features/mailer_spec.rb +16 -0
- data/spec/features/node_spec.rb +1 -1
- data/spec/features/pundit_spec.rb +34 -0
- data/spec/features/schedule_spec.rb +11 -4
- data/spec/features/testing_spec.rb +56 -0
- data/spec/support/potassium_test_helpers.rb +2 -3
- data/tmp/.keep +0 -0
- metadata +64 -15
- data/lib/potassium/assets/Dockerfile.ci +0 -6
- data/lib/potassium/assets/active_admin/admin_user_policy.rb +0 -2
- data/lib/potassium/assets/active_admin/comment_policy.rb +0 -2
- data/lib/potassium/assets/active_admin/pundit_page_policy.rb +0 -5
- data/lib/potassium/assets/bin/cibuild.erb +0 -117
- data/lib/potassium/assets/docker-compose.ci.yml +0 -12
- data/lib/potassium/assets/sidekiq_scheduler.yml +0 -9
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'simplecov_text_formatter'
|
3
|
+
require 'simplecov_linter_formatter'
|
4
|
+
|
5
|
+
SimpleCovLinterFormatter.setup do |config|
|
6
|
+
config.scope = ENV.fetch(
|
7
|
+
"SIMPLE_COV_LINTER_SCOPE", :own_changes
|
8
|
+
)
|
9
|
+
config.json_filename = ENV.fetch(
|
10
|
+
"SIMPLE_COV_LINTER_JSON_FILENAME", ".resultset.json"
|
11
|
+
)
|
12
|
+
config.summary_enabled = ENV.fetch(
|
13
|
+
"SIMPLE_COV_LINTER_SUMMARY_ENABLED", true
|
14
|
+
)
|
15
|
+
config.summary_enabled_bg = ENV.fetch(
|
16
|
+
"SIMPLE_COV_LINTER_SUMMARY_BG_ENABLED", true
|
17
|
+
)
|
18
|
+
config.summary_covered_bg_color = ENV.fetch(
|
19
|
+
"SIMPLE_COV_LINTER_SUMMARY_COVERED_BG_COLOR", :darkgreen
|
20
|
+
)
|
21
|
+
config.summary_not_covered_bg_color = ENV.fetch(
|
22
|
+
"SIMPLE_COV_LINTER_SUMMARY_NOT_COVERED_BG_COLOR", :firebrick
|
23
|
+
)
|
24
|
+
config.summary_text_color = ENV.fetch(
|
25
|
+
"SIMPLE_COV_LINTER_SUMMARY_TEXT_COLOR", :white
|
26
|
+
)
|
27
|
+
config.summary_files_sorting = ENV.fetch(
|
28
|
+
"SIMPLE_COV_LINTER_SUMMARY_FILES_SORTING", :coverage
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
SimpleCov.start 'rails' do
|
33
|
+
add_group 'Commands', 'app/commands'
|
34
|
+
add_group 'Services', 'app/services'
|
35
|
+
add_group 'Observers', 'app/observers'
|
36
|
+
add_group 'Policies', 'app/policies'
|
37
|
+
add_group 'Utils', 'app/utils'
|
38
|
+
add_group 'Extensions', 'app/extensions'
|
39
|
+
|
40
|
+
add_filter %r{app/controllers/([a-z]|_)*_controller.rb}
|
41
|
+
add_filter 'app/admin'
|
42
|
+
add_filter 'app/channels'
|
43
|
+
add_filter 'app/uploaders'
|
44
|
+
add_filter 'app/serializers'
|
45
|
+
add_filter 'app/clients'
|
46
|
+
add_filter 'app/helpers'
|
47
|
+
add_filter 'app/decorators'
|
48
|
+
add_filter 'app/responders'
|
49
|
+
add_filter 'lib/fake_data_loader.rb'
|
50
|
+
add_filter 'lib/vue_component.rb'
|
51
|
+
|
52
|
+
if ENV["CIRCLECI"]
|
53
|
+
formatter(SimpleCov::Formatter::TextFormatter)
|
54
|
+
else
|
55
|
+
formatter(
|
56
|
+
SimpleCov::Formatter::MultiFormatter.new(
|
57
|
+
[
|
58
|
+
SimpleCov::Formatter::LinterFormatter,
|
59
|
+
SimpleCov::Formatter::HTMLFormatter
|
60
|
+
]
|
61
|
+
)
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
@@ -97,10 +97,10 @@ module Potassium::CliOptions # rubocop:disable Metrics/ModuleLength
|
|
97
97
|
default_test_value: false
|
98
98
|
},
|
99
99
|
{
|
100
|
-
type: :
|
100
|
+
type: :switch,
|
101
101
|
name: "background_processor",
|
102
|
-
desc: "
|
103
|
-
default_test_value:
|
102
|
+
desc: "Whether to use Sidekiq for background processing or not",
|
103
|
+
default_test_value: false
|
104
104
|
},
|
105
105
|
{
|
106
106
|
type: :switch,
|
@@ -177,6 +177,14 @@ module Potassium::CliOptions # rubocop:disable Metrics/ModuleLength
|
|
177
177
|
desc: "Decides which front-end framework to use. Available: Vue, Angular 2, None",
|
178
178
|
default_test_value: "None"
|
179
179
|
},
|
180
|
+
{
|
181
|
+
type: :switch,
|
182
|
+
name: 'google_tag_manager',
|
183
|
+
desc: 'Whether to use google tag manager',
|
184
|
+
negatable: true,
|
185
|
+
default_value: 'none',
|
186
|
+
default_test_value: false
|
187
|
+
},
|
180
188
|
{
|
181
189
|
type: :switch,
|
182
190
|
name: "test",
|
@@ -184,6 +192,14 @@ module Potassium::CliOptions # rubocop:disable Metrics/ModuleLength
|
|
184
192
|
negatable: true,
|
185
193
|
default_value: false,
|
186
194
|
default_test_value: true
|
195
|
+
},
|
196
|
+
{
|
197
|
+
type: :switch,
|
198
|
+
name: "spring",
|
199
|
+
desc: "Whether to use Spring",
|
200
|
+
negatable: true,
|
201
|
+
default_value: true,
|
202
|
+
default_test_value: false
|
187
203
|
}
|
188
204
|
]
|
189
205
|
|
@@ -7,6 +7,10 @@ module TemplateHelpers
|
|
7
7
|
"#{Potassium::NODE_VERSION}.x"
|
8
8
|
end
|
9
9
|
|
10
|
+
def ruby_version
|
11
|
+
Semantic::Version.new(Potassium::RUBY_VERSION).instance_eval { "#{major}.#{minor}" }
|
12
|
+
end
|
13
|
+
|
10
14
|
def load_recipe(recipe_name)
|
11
15
|
@recipes ||= {}
|
12
16
|
@recipes[recipe_name] ||= get_recipe_class(recipe_name.to_sym).new(self)
|
@@ -32,12 +32,11 @@ class Recipes::Admin < Rails::AppBuilder
|
|
32
32
|
private
|
33
33
|
|
34
34
|
def add_active_admin
|
35
|
-
gather_gem 'activeadmin', '~> 2.
|
35
|
+
gather_gem 'activeadmin', '~> 2.9'
|
36
36
|
gather_gem 'activeadmin_addons'
|
37
|
-
gather_gem 'active_skin', github: 'SoftwareBrothers/active_skin'
|
38
37
|
add_readme_section :internal_dependencies, :active_admin
|
39
38
|
after(:gem_install, wrap_in_action: :admin_install) do
|
40
|
-
generate "active_admin:install"
|
39
|
+
generate "active_admin:install --use_webpacker"
|
41
40
|
line = "ActiveAdmin.setup do |config|"
|
42
41
|
initializer = "config/initializers/active_admin.rb"
|
43
42
|
gsub_file initializer, /(#{Regexp.escape(line)})/mi do |_match|
|
@@ -50,26 +49,37 @@ class Recipes::Admin < Rails::AppBuilder
|
|
50
49
|
end\n
|
51
50
|
ActiveAdmin.setup do |config|
|
52
51
|
config.view_factory.footer = CustomFooter
|
52
|
+
meta_tags_options = { viewport: 'width=device-width, initial-scale=1' }
|
53
|
+
config.meta_tags = meta_tags_options
|
54
|
+
config.meta_tags_for_logged_out_pages = meta_tags_options
|
53
55
|
HERE
|
54
56
|
end
|
55
57
|
|
56
|
-
|
57
|
-
style = "app/assets/stylesheets/active_admin.css.scss"
|
58
|
-
style = File.exist?(style) ? style : "app/assets/stylesheets/active_admin.scss"
|
58
|
+
generate "activeadmin_addons:install"
|
59
59
|
|
60
|
-
|
61
|
-
<<~HERE
|
62
|
-
#{line}
|
63
|
-
$skinActiveColor: #001CEE;
|
64
|
-
$skinHeaderBck: #002744;
|
65
|
-
$panelHeaderBck: #002744;
|
66
|
-
//$skinLogo: $skinHeaderBck image-url("logo_admin.png") no-repeat center center;
|
60
|
+
run "bin/yarn add arctic_admin @fortawesome/fontawesome-free"
|
67
61
|
|
68
|
-
|
69
|
-
HERE
|
70
|
-
end
|
62
|
+
aa_style = "app/javascript/stylesheets/active_admin.scss"
|
71
63
|
|
72
|
-
|
64
|
+
gsub_file(
|
65
|
+
aa_style,
|
66
|
+
"@import \"~@activeadmin/activeadmin/src/scss/mixins\";\n" +
|
67
|
+
"@import \"~@activeadmin/activeadmin/src/scss/base\";",
|
68
|
+
"@import '~arctic_admin/src/scss/main'; \n"
|
69
|
+
)
|
70
|
+
|
71
|
+
aa_js = "app/javascript/packs/active_admin.js"
|
72
|
+
js_line = "import \"@activeadmin/activeadmin\";\n"
|
73
|
+
|
74
|
+
gsub_file(
|
75
|
+
aa_js,
|
76
|
+
js_line,
|
77
|
+
<<~HERE
|
78
|
+
#{js_line}
|
79
|
+
import '@fortawesome/fontawesome-free/css/all.css';
|
80
|
+
import 'arctic_admin';
|
81
|
+
HERE
|
82
|
+
)
|
73
83
|
end
|
74
84
|
end
|
75
85
|
end
|
@@ -38,6 +38,8 @@ class Recipes::Api < Rails::AppBuilder
|
|
38
38
|
end
|
39
39
|
|
40
40
|
add_readme_section :internal_dependencies, :power_api
|
41
|
+
rubocop_example = "RSpec:\n Language:\n Includes:\n Examples:\n - run_test!"
|
42
|
+
append_to_file('.rubocop.yml', rubocop_example)
|
41
43
|
|
42
44
|
after(:gem_install) do
|
43
45
|
generate "power_api:install"
|
@@ -1,12 +1,12 @@
|
|
1
1
|
class Recipes::BackgroundProcessor < Rails::AppBuilder
|
2
2
|
def ask
|
3
|
-
response = if
|
3
|
+
response = if enabled_mailer?
|
4
|
+
info "Note: Emails should be sent on background jobs. We'll install sidekiq"
|
5
|
+
true
|
6
|
+
else
|
4
7
|
answer(:background_processor) do
|
5
8
|
Ask.confirm("Do you want to use Sidekiq for background job processing?")
|
6
9
|
end
|
7
|
-
else
|
8
|
-
info "Note: Emails should be sent on background jobs. We'll install sidekiq"
|
9
|
-
true
|
10
10
|
end
|
11
11
|
set(:background_processor, response)
|
12
12
|
end
|
@@ -30,6 +30,42 @@ class Recipes::BackgroundProcessor < Rails::AppBuilder
|
|
30
30
|
gem_exists?(/sidekiq/)
|
31
31
|
end
|
32
32
|
|
33
|
+
def add_sidekiq
|
34
|
+
recipe = self
|
35
|
+
run_action(:install_sidekiq) do
|
36
|
+
gather_gem("sidekiq")
|
37
|
+
recipe.add_adapters("sidekiq")
|
38
|
+
add_readme_section :internal_dependencies, :sidekiq
|
39
|
+
recipe.edit_procfile("bundle exec sidekiq")
|
40
|
+
append_to_file(".env.development", "DB_POOL=25\n")
|
41
|
+
template("../assets/sidekiq.rb.erb", "config/initializers/sidekiq.rb", force: true)
|
42
|
+
copy_file("../assets/sidekiq.yml", "config/sidekiq.yml", force: true)
|
43
|
+
copy_file("../assets/redis.yml", "config/redis.yml", force: true)
|
44
|
+
recipe.mount_sidekiq_routes
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def edit_procfile(cmd)
|
49
|
+
heroku = load_recipe(:heroku)
|
50
|
+
if selected?(:heroku) || heroku.installed?
|
51
|
+
gsub_file('Procfile', /^.*$/m) { |match| "#{match}worker: #{cmd}" }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_adapters(name)
|
56
|
+
application("config.active_job.queue_adapter = :#{name}")
|
57
|
+
application "config.active_job.queue_adapter = :async", env: "development"
|
58
|
+
application "config.active_job.queue_adapter = :test", env: "test"
|
59
|
+
end
|
60
|
+
|
61
|
+
def mount_sidekiq_routes
|
62
|
+
insert_into_file "config/routes.rb", after: "Rails.application.routes.draw do\n" do
|
63
|
+
<<-HERE.gsub(/^ {6}/, '')
|
64
|
+
mount Sidekiq::Web => '/queue'
|
65
|
+
HERE
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
33
69
|
private
|
34
70
|
|
35
71
|
def add_docker_compose_redis_config
|
@@ -59,33 +95,8 @@ class Recipes::BackgroundProcessor < Rails::AppBuilder
|
|
59
95
|
)
|
60
96
|
end
|
61
97
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
add_readme_section :internal_dependencies, :sidekiq
|
66
|
-
edit_procfile("bundle exec sidekiq")
|
67
|
-
append_to_file(".env.development", "DB_POOL=25\n")
|
68
|
-
template("../assets/sidekiq.rb.erb", "config/initializers/sidekiq.rb", force: true)
|
69
|
-
copy_file("../assets/sidekiq.yml", "config/sidekiq.yml", force: true)
|
70
|
-
copy_file("../assets/redis.yml", "config/redis.yml", force: true)
|
71
|
-
|
72
|
-
insert_into_file "config/routes.rb", after: "Rails.application.routes.draw do\n" do
|
73
|
-
<<-HERE.gsub(/^ {6}/, '')
|
74
|
-
mount Sidekiq::Web => '/queue'
|
75
|
-
HERE
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def edit_procfile(cmd)
|
80
|
-
heroku = load_recipe(:heroku)
|
81
|
-
if selected?(:heroku) || heroku.installed?
|
82
|
-
gsub_file('Procfile', /^.*$/m) { |match| "#{match}worker: #{cmd}" }
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def add_adapters(name)
|
87
|
-
application("config.active_job.queue_adapter = :#{name}")
|
88
|
-
application "config.active_job.queue_adapter = :async", env: "development"
|
89
|
-
application "config.active_job.queue_adapter = :test", env: "test"
|
98
|
+
def enabled_mailer?
|
99
|
+
mailer_answer = get(:email_service)
|
100
|
+
mailer_answer && ![:none, :None].include?(mailer_answer.to_sym)
|
90
101
|
end
|
91
102
|
end
|
data/lib/potassium/recipes/ci.rb
CHANGED
@@ -1,50 +1,20 @@
|
|
1
1
|
class Recipes::Ci < Rails::AppBuilder
|
2
2
|
def create
|
3
|
-
copy_file '../assets/Dockerfile.ci', 'Dockerfile.ci'
|
4
3
|
template '../assets/.circleci/config.yml.erb', '.circleci/config.yml'
|
5
4
|
|
6
|
-
template '../assets/bin/cibuild.erb', 'bin/cibuild'
|
7
|
-
run "chmod a+x bin/cibuild"
|
8
|
-
|
9
|
-
copy_file '../assets/docker-compose.ci.yml', 'docker-compose.ci.yml'
|
10
|
-
|
11
5
|
gather_gems(:test) do
|
12
|
-
gather_gem 'rspec_junit_formatter', '0.
|
13
|
-
end
|
14
|
-
|
15
|
-
compose = DockerHelpers.new('docker-compose.ci.yml')
|
16
|
-
|
17
|
-
if selected?(:database, :mysql)
|
18
|
-
srv =
|
19
|
-
<<~YAML
|
20
|
-
image: mysql:#{Potassium::MYSQL_VERSION}
|
21
|
-
environment:
|
22
|
-
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
|
23
|
-
YAML
|
24
|
-
compose.add_service("mysql", srv)
|
25
|
-
compose.add_link('test', 'mysql')
|
26
|
-
compose.add_env('test', 'MYSQL_HOST', 'mysql')
|
27
|
-
compose.add_env('test', 'MYSQL_PORT', '3306')
|
28
|
-
|
29
|
-
elsif selected?(:database, :postgresql)
|
30
|
-
srv =
|
31
|
-
<<~YAML
|
32
|
-
image: "postgres:#{Potassium::POSTGRES_VERSION}"
|
33
|
-
environment:
|
34
|
-
POSTGRES_USER: postgres
|
35
|
-
POSTGRES_PASSWORD: ''
|
36
|
-
YAML
|
37
|
-
compose.add_service("postgresql", srv)
|
38
|
-
compose.add_link('test', 'postgresql')
|
39
|
-
compose.add_env('test', 'DB_USER', 'postgres')
|
40
|
-
compose.add_env('test', 'DB_HOST', 'postgresql')
|
41
|
-
compose.add_env('test', 'DB_PORT', '5432')
|
6
|
+
gather_gem 'rspec_junit_formatter', '~> 0.4'
|
42
7
|
end
|
43
8
|
|
44
|
-
compose.add_volume('test_data')
|
45
|
-
|
46
9
|
add_readme_header :ci
|
47
|
-
|
48
10
|
application 'config.assets.js_compressor = :uglifier', env: 'test'
|
49
11
|
end
|
12
|
+
|
13
|
+
def install
|
14
|
+
create
|
15
|
+
end
|
16
|
+
|
17
|
+
def installed?
|
18
|
+
file_exist?('.circleci/config.yml')
|
19
|
+
end
|
50
20
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Recipes::Coverage < Rails::AppBuilder
|
2
|
+
def create
|
3
|
+
load_gems
|
4
|
+
configure_rails_helper
|
5
|
+
append_to_file('.gitignore', "/coverage/*\n")
|
6
|
+
end
|
7
|
+
|
8
|
+
def installed?
|
9
|
+
gem_exists?(/simplecov/)
|
10
|
+
end
|
11
|
+
|
12
|
+
def install
|
13
|
+
create
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def load_gems
|
19
|
+
gather_gems(:test) do
|
20
|
+
gather_gem 'simplecov'
|
21
|
+
gather_gem 'simplecov_linter_formatter', '~> 0.2'
|
22
|
+
gather_gem 'simplecov_text_formatter'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure_rails_helper
|
27
|
+
copy_file '../assets/testing/simplecov_config.rb', 'spec/simplecov_config.rb'
|
28
|
+
|
29
|
+
after(:gem_install) do
|
30
|
+
gsub_file 'spec/rails_helper.rb', "ENV['RACK_ENV'] ||= 'test'" do |match|
|
31
|
+
"#{match}\nrequire 'simplecov_config'"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -39,7 +39,7 @@ class Recipes::FileStorage < Rails::AppBuilder
|
|
39
39
|
|
40
40
|
def add_shrine
|
41
41
|
gather_gem('shrine', '~> 3.0')
|
42
|
-
gather_gem('marcel', '~> 0
|
42
|
+
gather_gem('marcel', '~> 1.0')
|
43
43
|
copy_file('../assets/config/shrine.rb', 'config/initializers/shrine.rb', force: true)
|
44
44
|
copy_file('../assets/app/uploaders/image_uploader.rb', 'app/uploaders/image_uploader.rb')
|
45
45
|
copy_file('../assets/app/uploaders/base_uploader.rb', 'app/uploaders/base_uploader.rb')
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class Recipes::FrontEnd < Rails::AppBuilder
|
2
|
+
VUE_LOADER_VERSION = Potassium::VUE_LOADER_VERSION
|
3
|
+
|
2
4
|
def ask
|
3
5
|
frameworks = {
|
4
6
|
vue: "Vue",
|
@@ -15,21 +17,13 @@ class Recipes::FrontEnd < Rails::AppBuilder
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def create
|
18
|
-
return if [:none, :None].include? get(:front_end).to_sym
|
19
|
-
|
20
20
|
recipe = self
|
21
21
|
after(:gem_install) do
|
22
22
|
value = get(:front_end)
|
23
23
|
run "rails webpacker:install"
|
24
|
-
run "rails webpacker:install:#{value}"
|
25
|
-
|
26
|
-
if value == :vue
|
27
|
-
recipe.setup_vue_with_compiler_build
|
28
|
-
recipe.setup_jest
|
29
|
-
if get(:api) == :graphql
|
30
|
-
recipe.setup_apollo
|
31
|
-
end
|
32
|
-
end
|
24
|
+
run "rails webpacker:install:#{value}" unless [:none, :None].include? value.to_sym
|
25
|
+
|
26
|
+
recipe.setup_vue if value == :vue
|
33
27
|
recipe.add_responsive_meta_tag
|
34
28
|
recipe.setup_tailwind
|
35
29
|
add_readme_header :webpack
|
@@ -69,7 +63,8 @@ class Recipes::FrontEnd < Rails::AppBuilder
|
|
69
63
|
end
|
70
64
|
|
71
65
|
def setup_tailwind
|
72
|
-
run
|
66
|
+
run "bin/yarn add tailwindcss@#{Potassium::TAILWINDCSS}"
|
67
|
+
specify_autoprefixer_postcss_compatibility_versions
|
73
68
|
setup_client_css
|
74
69
|
remove_server_css_requires
|
75
70
|
setup_tailwind_requirements
|
@@ -107,6 +102,19 @@ class Recipes::FrontEnd < Rails::AppBuilder
|
|
107
102
|
)
|
108
103
|
end
|
109
104
|
|
105
|
+
def foce_vue_loader_version
|
106
|
+
run "bin/yarn add vue-loader@#{VUE_LOADER_VERSION}"
|
107
|
+
end
|
108
|
+
|
109
|
+
def setup_vue
|
110
|
+
foce_vue_loader_version
|
111
|
+
setup_vue_with_compiler_build
|
112
|
+
setup_jest
|
113
|
+
if get(:api) == :graphql
|
114
|
+
setup_apollo
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
110
118
|
private
|
111
119
|
|
112
120
|
def frameworks(framework)
|
@@ -147,6 +155,10 @@ class Recipes::FrontEnd < Rails::AppBuilder
|
|
147
155
|
JS
|
148
156
|
end
|
149
157
|
|
158
|
+
def specify_autoprefixer_postcss_compatibility_versions
|
159
|
+
run 'bin/yarn -D add postcss@^7 autoprefixer@^9'
|
160
|
+
end
|
161
|
+
|
150
162
|
def setup_client_css
|
151
163
|
application_css = 'app/javascript/css/application.css'
|
152
164
|
create_file application_css, "", force: true
|
@@ -264,7 +276,8 @@ class Recipes::FrontEnd < Rails::AppBuilder
|
|
264
276
|
},
|
265
277
|
"snapshotSerializers": [
|
266
278
|
"<rootDir>/node_modules/jest-serializer-vue"
|
267
|
-
]
|
279
|
+
],
|
280
|
+
"testEnvironment": "jsdom"
|
268
281
|
}
|
269
282
|
}
|
270
283
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class Recipes::GoogleTagManager < Rails::AppBuilder
|
2
|
+
def ask
|
3
|
+
use_google_tag_manager = answer(:google_tag_manager) do
|
4
|
+
Ask.confirm 'Do you want to use Google Tag Manager?'
|
5
|
+
end
|
6
|
+
|
7
|
+
set(:google_tag_manager, use_google_tag_manager)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create
|
11
|
+
install if selected?(:google_tag_manager)
|
12
|
+
end
|
13
|
+
|
14
|
+
def install
|
15
|
+
add_google_tag_manager
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_google_tag_manager
|
19
|
+
copy_tag_manager_files
|
20
|
+
append_to_file '.env.development', "GTM_CONTAINER_ID=\n"
|
21
|
+
include_tag_manager
|
22
|
+
add_content_security_policy
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_content_security_policy
|
26
|
+
inject_into_file(
|
27
|
+
'config/initializers/content_security_policy.rb',
|
28
|
+
content_security_policy_code
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def copy_tag_manager_files
|
33
|
+
copy_file(
|
34
|
+
'../assets/app/views/shared/_gtm_head.html.erb',
|
35
|
+
'app/views/shared/_gtm_head.html.erb',
|
36
|
+
force: true
|
37
|
+
)
|
38
|
+
|
39
|
+
copy_file(
|
40
|
+
'../assets/app/views/shared/_gtm_body.html.erb',
|
41
|
+
'app/views/shared/_gtm_body.html.erb',
|
42
|
+
force: true
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def include_tag_manager
|
47
|
+
inject_into_file(
|
48
|
+
'app/views/layouts/application.html.erb',
|
49
|
+
render_string('shared/gtm_head'),
|
50
|
+
before: '</head>'
|
51
|
+
)
|
52
|
+
|
53
|
+
inject_into_file(
|
54
|
+
'app/views/layouts/application.html.erb',
|
55
|
+
render_string('shared/gtm_body'),
|
56
|
+
after: '<body>'
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def render_string(file_path)
|
63
|
+
" <%if Rails.env.production? %>
|
64
|
+
<%= render \"#{file_path}\" %>
|
65
|
+
<% end %>\n "
|
66
|
+
end
|
67
|
+
|
68
|
+
def content_security_policy_code
|
69
|
+
<<~HERE
|
70
|
+
Rails.application.config.content_security_policy do |policy|
|
71
|
+
policy.connect_src(
|
72
|
+
:self,
|
73
|
+
:https,
|
74
|
+
'http://localhost:3035',
|
75
|
+
'ws://localhost:3035',
|
76
|
+
'https://www.google-analytics.com'
|
77
|
+
)
|
78
|
+
# google tag manager requires to enable unsafe inline and vue unsave eval:
|
79
|
+
# https://developers.google.com/tag-manager/web/csp
|
80
|
+
# https://vuejs.org/v2/guide/installation.html#CSP-environments
|
81
|
+
policy.script_src(
|
82
|
+
:self,
|
83
|
+
:https,
|
84
|
+
:unsafe_inline,
|
85
|
+
:unsafe_eval,
|
86
|
+
'https://www.googletagmanager.com',
|
87
|
+
'https://www.google-analytics.com',
|
88
|
+
'https://ssl.google-analytics.com'
|
89
|
+
)
|
90
|
+
policy.img_src :self, :https, 'https://www.googletagmanager.com', 'https://www.google-analytics.com'
|
91
|
+
end
|
92
|
+
HERE
|
93
|
+
end
|
94
|
+
end
|