potassium 6.3.0 → 6.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.node-version +1 -1
  4. data/CHANGELOG.md +45 -0
  5. data/README.md +30 -3
  6. data/docs/CONTRIBUTING.md +2 -2
  7. data/lib/potassium/assets/.circleci/config.yml.erb +40 -12
  8. data/lib/potassium/assets/.eslintrc.json +15 -9
  9. data/lib/potassium/assets/.pryrc +0 -6
  10. data/lib/potassium/assets/.rubocop.yml +1 -0
  11. data/lib/potassium/assets/Aptfile +5 -0
  12. data/lib/potassium/assets/README.yml +74 -7
  13. data/lib/potassium/assets/active_admin/admin-component.vue +22 -30
  14. data/lib/potassium/assets/active_admin/policies/admin_user_policy.rb +2 -0
  15. data/lib/potassium/assets/active_admin/policies/comment_policy.rb +2 -0
  16. data/lib/potassium/assets/active_admin/policies/default_policy.rb +49 -0
  17. data/lib/potassium/assets/active_admin/policies/page_policy.rb +2 -0
  18. data/lib/potassium/assets/app/javascript/{app.spec.js → components/app.spec.ts} +2 -2
  19. data/lib/potassium/assets/app/javascript/components/app.vue +9 -0
  20. data/lib/potassium/assets/app/javascript/types/vue.d.ts +5 -0
  21. data/lib/potassium/assets/app/jobs/shrine_promote_job.rb +14 -0
  22. data/lib/potassium/assets/app/mailers/application_mailer.rb +1 -1
  23. data/lib/potassium/assets/app/mailers/example_mailer.rb +6 -0
  24. data/lib/potassium/assets/app/serializers/base_serializer.rb +3 -0
  25. data/lib/potassium/assets/app/serializers/concerns/image_handling_attributes.rb +20 -0
  26. data/lib/potassium/assets/app/uploaders/cover_image_uploader.rb +52 -0
  27. data/lib/potassium/assets/app/views/example_mailer/example_mail.html.mjml +7 -0
  28. data/lib/potassium/assets/app/views/layouts/default_mail.html.mjml +49 -0
  29. data/lib/potassium/assets/config/initializers/shrine/plugins/image_handling_utilities.rb +143 -0
  30. data/lib/potassium/assets/config/mailer.rb.erb +0 -2
  31. data/lib/potassium/assets/config/shrine.rb +15 -0
  32. data/lib/potassium/assets/config/webpack/rules/css.js +5 -0
  33. data/lib/potassium/assets/config/webpack/rules/index.js +11 -0
  34. data/lib/potassium/assets/config/webpack/rules/jquery.js +11 -0
  35. data/lib/potassium/assets/config/webpack/rules/typescript.js +32 -0
  36. data/lib/potassium/assets/config/webpack/rules/vue.js +19 -0
  37. data/lib/potassium/assets/config/webpack/webpack.config.js +4 -0
  38. data/lib/potassium/assets/public/mails/platanus-logo.png +0 -0
  39. data/lib/potassium/assets/testing/.rspec +1 -0
  40. data/lib/potassium/assets/testing/devise_config.rb +6 -0
  41. data/lib/potassium/assets/testing/factory_bot_config.rb +3 -0
  42. data/lib/potassium/assets/testing/faker_config.rb +1 -0
  43. data/lib/potassium/assets/testing/power_types_config.rb +1 -0
  44. data/lib/potassium/assets/testing/rails_helper.rb +130 -49
  45. data/lib/potassium/assets/testing/shoulda_matchers_config.rb +8 -0
  46. data/lib/potassium/assets/testing/simplecov_config.rb +64 -0
  47. data/lib/potassium/assets/testing/system_tests_config.rb +6 -0
  48. data/lib/potassium/assets/tsconfig.json +31 -0
  49. data/lib/potassium/cli/commands/create.rb +3 -1
  50. data/lib/potassium/cli_options.rb +23 -3
  51. data/lib/potassium/platanus_config.rb +20 -0
  52. data/lib/potassium/recipes/admin.rb +37 -16
  53. data/lib/potassium/recipes/api.rb +8 -85
  54. data/lib/potassium/recipes/coverage.rb +66 -0
  55. data/lib/potassium/recipes/file_storage.rb +50 -0
  56. data/lib/potassium/recipes/front_end.rb +87 -108
  57. data/lib/potassium/recipes/google_tag_manager.rb +20 -16
  58. data/lib/potassium/recipes/heroku.rb +1 -2
  59. data/lib/potassium/recipes/mailer.rb +22 -10
  60. data/lib/potassium/recipes/mjml.rb +31 -0
  61. data/lib/potassium/recipes/node.rb +11 -13
  62. data/lib/potassium/recipes/pundit.rb +29 -10
  63. data/lib/potassium/recipes/rails.rb +0 -4
  64. data/lib/potassium/recipes/spring.rb +9 -0
  65. data/lib/potassium/recipes/style.rb +9 -2
  66. data/lib/potassium/recipes/testing.rb +75 -18
  67. data/lib/potassium/recipes/vue_admin.rb +38 -8
  68. data/lib/potassium/templates/application.rb +5 -2
  69. data/lib/potassium/version.rb +10 -4
  70. data/spec/features/api_spec.rb +6 -1
  71. data/spec/features/ci_spec.rb +1 -1
  72. data/spec/features/coverage_spec.rb +43 -0
  73. data/spec/features/file_storage_spec.rb +102 -26
  74. data/spec/features/front_end_spec.rb +16 -47
  75. data/spec/features/google_tag_manager_spec.rb +1 -24
  76. data/spec/features/heroku_spec.rb +0 -4
  77. data/spec/features/mailer_spec.rb +79 -33
  78. data/spec/features/mjml_spec.rb +53 -0
  79. data/spec/features/node_spec.rb +1 -1
  80. data/spec/features/pundit_spec.rb +34 -0
  81. data/spec/features/testing_spec.rb +56 -0
  82. data/spec/features/vue_admin_spec.rb +0 -10
  83. data/spec/support/potassium_test_helpers.rb +2 -2
  84. data/spec/support/shared_examples.rb +5 -0
  85. metadata +50 -27
  86. data/lib/potassium/assets/active_admin/admin_application.js +0 -14
  87. data/lib/potassium/assets/active_admin/admin_user_policy.rb +0 -2
  88. data/lib/potassium/assets/active_admin/comment_policy.rb +0 -2
  89. data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +0 -10
  90. data/lib/potassium/assets/active_admin/pundit_page_policy.rb +0 -5
  91. data/lib/potassium/assets/app/graphql/graphql_controller.rb +0 -55
  92. data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +0 -23
  93. data/lib/potassium/assets/app/graphql/queries/base_query.rb +0 -4
  94. data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +0 -4
  95. data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +0 -4
  96. data/lib/potassium/assets/app/graphql/types/base/base_field.rb +0 -5
  97. data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +0 -5
  98. data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +0 -7
  99. data/lib/potassium/assets/app/graphql/types/base/base_object.rb +0 -5
  100. data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +0 -4
  101. data/lib/potassium/assets/app/graphql/types/base/base_union.rb +0 -4
  102. data/lib/potassium/assets/app/graphql/types/mutation_type.rb +0 -10
  103. data/lib/potassium/assets/app/graphql/types/query_type.rb +0 -13
  104. data/lib/potassium/assets/config/graphql_playground.rb +0 -20
  105. data/spec/features/graphql_spec.rb +0 -71
@@ -1,8 +1,15 @@
1
1
  class Recipes::FrontEnd < Rails::AppBuilder
2
+ VUE_LOADER_VERSION = Potassium::VUE_LOADER_VERSION
3
+ VUE_VERSION = Potassium::VUE_VERSION
4
+ VUE_TEST_UTILS_VERSION = Potassium::VUE_TEST_UTILS_VERSION
5
+ POSTCSS_VERSION = Potassium::POSTCSS_VERSION
6
+ TAILWINDCSS_VERSION = Potassium::TAILWINDCSS_VERSION
7
+ AUTOPREFIXER_VERSION = Potassium::AUTOPREFIXER_VERSION
8
+ VUE_JEST_VERSION = Potassium::VUE_JEST_VERSION
9
+
2
10
  def ask
3
11
  frameworks = {
4
12
  vue: "Vue",
5
- angular: "Angular 2",
6
13
  none: "None"
7
14
  }
8
15
 
@@ -15,21 +22,17 @@ class Recipes::FrontEnd < Rails::AppBuilder
15
22
  end
16
23
 
17
24
  def create
18
- return if [:none, :None].include? get(:front_end).to_sym
19
-
25
+ gather_gem('shakapacker', '~> 6.2.0')
20
26
  recipe = self
21
- after(:gem_install) do
22
- value = get(:front_end)
27
+ after(:gem_install, wrap_in_action: :webpacker_install) do
23
28
  run "rails webpacker:install"
24
- run "rails webpacker:install:#{value}" if 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
29
+ end
30
+ after(:webpacker_install) do
31
+ value = get(:front_end)
32
+ recipe.copy_webpack_rules
33
+ recipe.add_assets_path
34
+ recipe.setup_typescript
35
+ recipe.setup_vue if value == :vue
33
36
  recipe.add_responsive_meta_tag
34
37
  recipe.setup_tailwind
35
38
  add_readme_header :webpack
@@ -44,13 +47,37 @@ class Recipes::FrontEnd < Rails::AppBuilder
44
47
  def installed?
45
48
  package_file = 'package.json'
46
49
  return false unless file_exist?(package_file)
50
+
47
51
  package_content = read_file(package_file)
48
- package_content.include?("\"@angular/core\"") || package_content.include?("\"vue\"")
52
+ package_content.include?("\"vue\"")
53
+ end
54
+
55
+ def copy_webpack_rules
56
+ copy_file '../assets/config/webpack/webpack.config.js',
57
+ 'config/webpack/webpack.config.js',
58
+ force: true
59
+ copy_file '../assets/config/webpack/rules/index.js', 'config/webpack/rules/index.js'
60
+ copy_file '../assets/config/webpack/rules/css.js', 'config/webpack/rules/css.js'
61
+ copy_file '../assets/config/webpack/rules/vue.js', 'config/webpack/rules/vue.js'
62
+ copy_file '../assets/config/webpack/rules/jquery.js', 'config/webpack/rules/jquery.js'
63
+ copy_file '../assets/config/webpack/rules/typescript.js', 'config/webpack/rules/typescript.js'
64
+ end
65
+
66
+ def add_assets_path
67
+ gsub_file(
68
+ 'config/webpacker.yml',
69
+ 'additional_paths: []',
70
+ "additional_paths: ['app/assets']"
71
+ )
72
+ end
73
+
74
+ def setup_typescript
75
+ run "bin/yarn add typescript fork-ts-checker-webpack-plugin ts-loader @types/node"
76
+ copy_file '../assets/tsconfig.json', 'tsconfig.json'
49
77
  end
50
78
 
51
79
  def setup_vue_with_compiler_build
52
- application_js = 'app/javascript/packs/application.js'
53
- remove_file "app/javascript/packs/hello_vue.js"
80
+ application_js = 'app/javascript/application.js'
54
81
  create_file application_js, application_js_content, force: true
55
82
 
56
83
  layout_file = "app/views/layouts/application.html.erb"
@@ -69,43 +96,44 @@ class Recipes::FrontEnd < Rails::AppBuilder
69
96
  end
70
97
 
71
98
  def setup_tailwind
72
- run "bin/yarn add tailwindcss@#{Potassium::TAILWINDCSS}"
73
- specify_autoprefixer_postcss_compatibility_versions
99
+ run "bin/yarn add css-loader style-loader mini-css-extract-plugin @types/tailwindcss "\
100
+ "css-minimizer-webpack-plugin postcss@#{POSTCSS_VERSION} postcss-loader "\
101
+ "tailwindcss@#{TAILWINDCSS_VERSION} autoprefixer@#{AUTOPREFIXER_VERSION} sass sass-loader "\
102
+ "eslint-plugin-tailwindcss"
103
+ run "npx tailwindcss init -p"
74
104
  setup_client_css
75
105
  remove_server_css_requires
76
106
  setup_tailwind_requirements
77
107
  end
78
108
 
79
109
  def setup_jest
80
- run 'bin/yarn add jest vue-jest babel-jest @vue/test-utils jest-serializer-vue babel-core@^7.0.0-bridge.0 --dev'
110
+ run "bin/yarn add jest @vue/vue3-jest@#{VUE_JEST_VERSION} babel-jest "\
111
+ "@vue/test-utils@#{VUE_TEST_UTILS_VERSION} ts-jest"
81
112
  json_file = File.read(Pathname.new("package.json"))
82
113
  js_package = JSON.parse(json_file)
83
114
  js_package = js_package.merge(jest_config)
84
115
  json_string = JSON.pretty_generate(js_package)
85
116
  create_file 'package.json', json_string, force: true
86
117
 
87
- copy_file '../assets/app/javascript/app.spec.js', 'app/javascript/app.spec.js'
118
+ copy_file '../assets/app/javascript/components/app.spec.ts',
119
+ 'app/javascript/components/app.spec.ts'
88
120
  end
89
121
 
90
- def setup_apollo
91
- run 'bin/yarn add vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag'
92
-
93
- inject_into_file(
94
- 'app/javascript/packs/application.js',
95
- apollo_imports,
96
- after: "import App from '../app.vue';"
97
- )
98
-
99
- inject_into_file(
100
- 'app/javascript/packs/application.js',
101
- apollo_loading,
102
- after: "import VueApollo from 'vue-apollo';"
103
- )
104
- inject_into_file(
105
- 'app/javascript/packs/application.js',
106
- "\n apolloProvider,",
107
- after: "components: { App },"
122
+ def setup_vue
123
+ run "bin/yarn add vue@#{VUE_VERSION} vue-loader@#{VUE_LOADER_VERSION} "\
124
+ "babel-preset-typescript-vue3"
125
+ gsub_file(
126
+ 'config/webpack/webpack.config.js',
127
+ ' merge(typescriptConfig, cssConfig, jQueryConfig, webpackConfig);',
128
+ ' merge(vueConfig, typescriptConfig, cssConfig, jQueryConfig, webpackConfig);'
108
129
  )
130
+ copy_file '../assets/app/javascript/components/app.vue', 'app/javascript/components/app.vue'
131
+ copy_file '../assets/app/javascript/types/vue.d.ts', 'app/javascript/types/vue.d.ts'
132
+ setup_vue_with_compiler_build
133
+ recipe = self
134
+ run_action(:setup_jest) do
135
+ recipe.setup_jest
136
+ end
109
137
  end
110
138
 
111
139
  private
@@ -113,45 +141,11 @@ class Recipes::FrontEnd < Rails::AppBuilder
113
141
  def frameworks(framework)
114
142
  frameworks = {
115
143
  vue: "vue",
116
- angular: "angular",
117
144
  none: nil
118
145
  }
119
146
  frameworks[framework]
120
147
  end
121
148
 
122
- def apollo_imports
123
- <<~JS
124
- \n
125
- import { ApolloClient } from 'apollo-client';
126
- import { createHttpLink } from 'apollo-link-http';
127
- import { InMemoryCache } from 'apollo-cache-inmemory';
128
- import VueApollo from 'vue-apollo';
129
- JS
130
- end
131
-
132
- def apollo_loading
133
- <<~JS
134
- \n
135
- const httpLink = createHttpLink({
136
- uri: `${window.location.origin}/graphql`,
137
- })
138
- const cache = new InMemoryCache()
139
- const apolloClient = new ApolloClient({
140
- link: httpLink,
141
- cache,
142
- })
143
-
144
- Vue.use(VueApollo)
145
- const apolloProvider = new VueApollo({
146
- defaultClient: apolloClient,
147
- })
148
- JS
149
- end
150
-
151
- def specify_autoprefixer_postcss_compatibility_versions
152
- run 'bin/yarn -D add postcss@^7 autoprefixer@^9'
153
- end
154
-
155
149
  def setup_client_css
156
150
  application_css = 'app/javascript/css/application.css'
157
151
  create_file application_css, "", force: true
@@ -160,14 +154,14 @@ class Recipes::FrontEnd < Rails::AppBuilder
160
154
  layout_file = "app/views/layouts/application.html.erb"
161
155
  insert_into_file layout_file, stylesheet_pack_tag, before: "</head>"
162
156
 
163
- application_js = 'app/javascript/packs/application.js'
157
+ application_js = 'app/javascript/application.js'
164
158
  if get(:front_end) != :vue
165
- create_file application_js, "import '../css/application.css';\n", force: true
159
+ create_file application_js, "import './css/application.css';\n", force: true
166
160
  else
167
161
  insert_into_file(
168
162
  application_js,
169
- "\nimport '../css/application.css';",
170
- after: "import App from '../app.vue';"
163
+ "\nimport './css/application.css';",
164
+ after: "import App from './components/app.vue';"
171
165
  )
172
166
  end
173
167
  end
@@ -178,9 +172,6 @@ class Recipes::FrontEnd < Rails::AppBuilder
178
172
 
179
173
  tailwind_config = 'tailwind.config.js'
180
174
  create_file tailwind_config, tailwind_config_content, force: true
181
-
182
- postcss_file = 'postcss.config.js'
183
- insert_into_file postcss_file, postcss_require_tailwind, after: "plugins: [\n"
184
175
  end
185
176
 
186
177
  def remove_server_css_requires
@@ -190,14 +181,14 @@ class Recipes::FrontEnd < Rails::AppBuilder
190
181
 
191
182
  def application_js_content
192
183
  <<~JS
193
- import Vue from 'vue/dist/vue.esm';
194
- import App from '../app.vue';
184
+ import { createApp } from 'vue';
185
+ import App from './components/app.vue';
195
186
 
196
187
  document.addEventListener('DOMContentLoaded', () => {
197
- const app = new Vue({
198
- el: '#vue-app',
188
+ const app = createApp({
199
189
  components: { App },
200
190
  });
191
+ app.mount('#vue-app');
201
192
 
202
193
  return app;
203
194
  });
@@ -206,9 +197,9 @@ class Recipes::FrontEnd < Rails::AppBuilder
206
197
 
207
198
  def tailwind_client_css
208
199
  <<~CSS
209
- @import 'tailwindcss/base';
210
- @import 'tailwindcss/components';
211
- @import 'tailwindcss/utilities';
200
+ @tailwind base;
201
+ @tailwind components;
202
+ @tailwind utilities;
212
203
  CSS
213
204
  end
214
205
 
@@ -221,26 +212,16 @@ class Recipes::FrontEnd < Rails::AppBuilder
221
212
  },
222
213
  variants: {},
223
214
  plugins: [],
224
- purge: {
225
- enabled: process.env.NODE_ENV === 'production',
226
- content: [
227
- './app/**/*.html',
228
- './app/**/*.vue',
229
- './app/**/*.js',
230
- './app/**/*.erb',
231
- ],
232
- }
215
+ content: [
216
+ './app/**/*.html',
217
+ './app/**/*.vue',
218
+ './app/**/*.js',
219
+ './app/**/*.erb',
220
+ ],
233
221
  };
234
222
  JS
235
223
  end
236
224
 
237
- def postcss_require_tailwind
238
- <<-JS.gsub(/^ {4}/, ' ')
239
- require('tailwindcss'),
240
- require('autoprefixer'),
241
- JS
242
- end
243
-
244
225
  def jest_config
245
226
  {
246
227
  "scripts": {
@@ -260,16 +241,14 @@ class Recipes::FrontEnd < Rails::AppBuilder
260
241
  },
261
242
  "moduleFileExtensions": [
262
243
  "js",
244
+ "ts",
263
245
  "json",
264
246
  "vue"
265
247
  ],
266
248
  "transform": {
267
- "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
268
- ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
249
+ "^.+\\.ts$": "ts-jest",
250
+ ".*\\.(vue)$": "@vue/vue3-jest"
269
251
  },
270
- "snapshotSerializers": [
271
- "<rootDir>/node_modules/jest-serializer-vue"
272
- ],
273
252
  "testEnvironment": "jsdom"
274
253
  }
275
254
  }
@@ -68,22 +68,26 @@ class Recipes::GoogleTagManager < Rails::AppBuilder
68
68
  def content_security_policy_code
69
69
  <<~HERE
70
70
  Rails.application.config.content_security_policy do |policy|
71
- if Rails.env.development?
72
- policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035'
73
- policy.script_src :self, :https, :unsafe_eval
74
- else
75
- policy.script_src :self, :https
76
- # google tag manager requires to enable unsafe inline:
77
- # https://developers.google.com/tag-manager/web/csp
78
- policy.connect_src :self, :https, 'https://www.google-analytics.com'
79
- policy.script_src :self,
80
- :https,
81
- :unsafe_inline,
82
- 'https://www.googletagmanager.com',
83
- 'https://www.google-analytics.com',
84
- 'https://ssl.google-analytics.com'
85
- policy.img_src :self, :https, 'https://www.googletagmanager.com', 'https://www.google-analytics.com'
86
- end
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, 'data:', :https, 'https://www.googletagmanager.com', 'https://www.google-analytics.com'
87
91
  end
88
92
  HERE
89
93
  end
@@ -24,14 +24,13 @@ class Recipes::Heroku < Rails::AppBuilder
24
24
  end
25
25
 
26
26
  def installed?
27
- gem_exists?(/rails_stdout_logging/)
27
+ gem_exists?(/heroku-stage/)
28
28
  end
29
29
 
30
30
  private
31
31
 
32
32
  def add_heroku
33
33
  gather_gems(:production) do
34
- gather_gem('rails_stdout_logging')
35
34
  gather_gem('heroku-stage')
36
35
  end
37
36
 
@@ -63,20 +63,32 @@ class Recipes::Mailer < Rails::AppBuilder
63
63
  gather_gem 'recipient_interceptor'
64
64
  end
65
65
 
66
+ def config_environments
67
+ gsub_file 'config/environments/production.rb', /$\s*config.action_mailer.*/, ''
68
+ asset_host_dev = <<~RUBY
69
+ config.action_mailer.asset_host = "http://\#{ENV.fetch('APPLICATION_HOST')}"
70
+ RUBY
71
+ application asset_host_dev, env: "development"
72
+ asset_host_prod = <<~RUBY
73
+ config.action_mailer.asset_host = "https://\#{ENV.fetch('APPLICATION_HOST')}"
74
+ RUBY
75
+ application asset_host_prod, env: "production"
76
+ mailer_config = <<~RUBY
77
+ require Rails.root.join("config", "mailer")
78
+ RUBY
79
+
80
+ prepend_file "config/environments/production.rb", mailer_config
81
+ end
82
+
66
83
  def config(service)
67
84
  template "../assets/config/mailer.rb.erb", 'config/mailer.rb'
68
- gsub_file 'config/environments/production.rb', /$\s*config.action_mailer.*/, ''
85
+
69
86
  append_to_file '.env.development', "APPLICATION_HOST=localhost:3000\n"
70
87
  append_to_file '.env.development', "EMAIL_RECIPIENTS=\n"
71
88
 
72
- mailer_config =
73
- <<~RUBY
74
- require Rails.root.join("config", "mailer")
75
- RUBY
76
-
77
- prepend_file "config/environments/production.rb", mailer_config
78
- copy_file '../assets/app/mailers/application_mailer.rb', 'app/mailers/application_mailer.rb', force: true
79
-
89
+ copy_file '../assets/app/mailers/application_mailer.rb', 'app/mailers/application_mailer.rb',
90
+ force: true
91
+ config_environments
80
92
  send(service[:name])
81
93
  end
82
94
 
@@ -88,7 +100,7 @@ class Recipes::Mailer < Rails::AppBuilder
88
100
  }
89
101
  RUBY
90
102
  inject_into_file 'config/mailer.rb', sendgrid_settings,
91
- after: "Rails.application.config.action_mailer.delivery_method = :sendgrid\n"
103
+ after: "Rails.application.config.action_mailer.delivery_method = :sendgrid\n"
92
104
  sendgrid_dev_settings = <<~RUBY
93
105
  Rails.application.config.action_mailer.sendgrid_dev_settings = {
94
106
  api_key: ENV['SENDGRID_API_KEY']
@@ -0,0 +1,31 @@
1
+ class Recipes::Mjml < Rails::AppBuilder
2
+ def create
3
+ return if get(:email_service).to_s.downcase.to_sym == :none
4
+
5
+ gather_gem 'mjml-rails'
6
+ after(:gem_install) do
7
+ run 'bin/yarn add mjml'
8
+ mjml_config
9
+ end
10
+ end
11
+
12
+ def installed?
13
+ gem_exists?(/mjml-rails/)
14
+ end
15
+
16
+ def install
17
+ create
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def mjml_config
24
+ copy_file '../assets/app/views/layouts/default_mail.html.mjml',
25
+ 'app/views/layouts/default_mail.html.mjml', force: true
26
+ copy_file '../assets/app/mailers/example_mailer.rb', 'app/mailers/example_mailer.rb', force: true
27
+ copy_file '../assets/app/views/example_mailer/example_mail.html.mjml',
28
+ 'app/views/example_mailer/example_mail.html.mjml', force: true
29
+ copy_file '../assets/public/mails/platanus-logo.png',
30
+ 'public/mails/platanus-logo.png', force: true
31
+ end
@@ -3,19 +3,17 @@ require 'semantic'
3
3
  require 'json'
4
4
 
5
5
  class Recipes::Node < Rails::AppBuilder
6
- def create
7
- info "Using node version LTS #{version}"
8
- create_file '.node-version', version, force: true
9
- json_file = File.read(Pathname.new("package.json"))
10
- js_package = JSON.parse(json_file)
11
- js_package["engines"] = { "node" => "#{version}.x" }
12
- json_string = JSON.pretty_generate(js_package)
13
- create_file 'package.json', json_string, force: true
14
- end
6
+ NODE_VERSION = Potassium::NODE_VERSION
15
7
 
16
- private
17
-
18
- def version
19
- Potassium::NODE_VERSION
8
+ def create
9
+ info "Using node version LTS #{NODE_VERSION}"
10
+ create_file '.node-version', NODE_VERSION, force: true
11
+ after(:webpacker_install) do
12
+ json_file = File.read(Pathname.new("package.json"))
13
+ js_package = JSON.parse(json_file)
14
+ js_package["engines"] = { "node" => "#{NODE_VERSION}.x" }
15
+ json_string = JSON.pretty_generate(js_package)
16
+ create_file 'package.json', json_string, force: true
17
+ end
20
18
  end
21
19
  end
@@ -31,20 +31,39 @@ class Recipes::Pundit < Rails::AppBuilder
31
31
  end
32
32
 
33
33
  def install_admin_pundit
34
+ configure_active_admin_initializer
35
+ copy_policies
36
+ end
37
+
38
+ private
39
+
40
+ def configure_active_admin_initializer
41
+ config_active_admin_option("authorization_adapter", "ActiveAdmin::PunditAdapter")
42
+ config_active_admin_option("pundit_default_policy", "'BackOffice::DefaultPolicy'")
43
+ config_active_admin_option("pundit_policy_namespace", ":back_office")
44
+ end
45
+
46
+ def copy_policies
47
+ copy_policy("default_policy")
48
+ copy_policy("admin_user_policy")
49
+ copy_policy("page_policy", "active_admin")
50
+ copy_policy("comment_policy", "active_admin")
51
+ end
52
+
53
+ def config_active_admin_option(option, value)
34
54
  initializer = "config/initializers/active_admin.rb"
35
- gsub_file initializer, /# config\.authorization_adapter =[^\n]+\n/ do
36
- "config.authorization_adapter = ActiveAdmin::PunditAdapter\n"
55
+ gsub_file initializer, /# config\.#{option} =[^\n]+\n/ do
56
+ "config.#{option} = #{value}\n"
37
57
  end
38
-
39
- template "../assets/active_admin/pundit_page_policy.rb",
40
- "app/policies/active_admin/page_policy.rb"
41
- template "../assets/active_admin/comment_policy.rb",
42
- "app/policies/active_admin/comment_policy.rb"
43
- template "../assets/active_admin/admin_user_policy.rb",
44
- "app/policies/admin_user_policy.rb"
45
58
  end
46
59
 
47
- private
60
+ def copy_policy(policy_name, model_namespace = nil)
61
+ destination_path = [model_namespace, policy_name].compact.join("/")
62
+ template(
63
+ "../assets/active_admin/policies/#{policy_name}.rb",
64
+ "app/policies/back_office/#{destination_path}.rb"
65
+ )
66
+ end
48
67
 
49
68
  def run_pundit_installer
50
69
  gather_gem 'pundit'
@@ -1,10 +1,6 @@
1
1
  class Recipes::Rails < Rails::AppBuilder
2
2
  def create
3
3
  gather_gem("bootsnap", require: false)
4
- gather_gems(:development) do
5
- gather_gem("spring")
6
- end
7
-
8
4
  environment 'config.force_ssl = true', env: 'production'
9
5
  disable_automatic_nonce_generation
10
6
  end
@@ -0,0 +1,9 @@
1
+ class Recipes::Spring < Rails::AppBuilder
2
+ def create
3
+ if answer(:spring)
4
+ gather_gems(:development) do
5
+ gather_gem("spring")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -17,9 +17,16 @@ class Recipes::Style < Rails::AppBuilder
17
17
  gather_gem 'rubocop-performance'
18
18
  gather_gem 'rubocop-rails'
19
19
  gather_gem 'rubocop-rspec', Potassium::RUBOCOP_RSPEC_VERSION
20
+ gather_gem 'rubocop-platanus'
21
+ end
22
+
23
+ after(:webpacker_install) do
24
+ run "yarn add --dev stylelint eslint eslint-plugin-import "\
25
+ "@typescript-eslint/eslint-plugin @types/jest @typescript-eslint/parser eslint-plugin-jest"
26
+ if selected?(:front_end, :vue)
27
+ run 'yarn add --dev eslint-plugin-vue @vue/eslint-config-typescript'
28
+ end
20
29
  end
21
- run 'bin/yarn add --dev stylelint eslint eslint-plugin-import'
22
- run 'bin/yarn add --dev eslint-plugin-vue' if selected?(:front_end, :vue)
23
30
  end
24
31
 
25
32
  def add_config_files