potassium 5.2.3 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +22 -9
- data/.node-version +1 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +26 -0
- data/docs/DSL.md +5 -5
- data/lib/potassium/assets/.circleci/config.yml.erb +102 -0
- data/lib/potassium/assets/.eslintrc.json +343 -0
- data/lib/potassium/assets/.rubocop.yml +515 -0
- data/lib/potassium/assets/.stylelintrc.json +46 -0
- data/lib/potassium/assets/Dockerfile.ci +1 -1
- data/lib/potassium/assets/Makefile.erb +6 -32
- data/lib/potassium/assets/README.yml +51 -7
- data/lib/potassium/assets/active_admin/admin-component.vue +35 -0
- data/lib/potassium/assets/active_admin/admin_application.js +14 -0
- data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +10 -0
- data/lib/potassium/assets/api/base_controller.rb +1 -3
- data/lib/potassium/assets/app/javascript/app.spec.js +14 -0
- data/lib/potassium/assets/app/uploaders/base_uploader.rb +13 -0
- data/lib/potassium/assets/app/uploaders/image_uploader.rb +5 -0
- data/lib/potassium/assets/bin/cibuild.erb +18 -1
- data/lib/potassium/assets/bin/setup.erb +1 -1
- data/lib/potassium/assets/config/database_mysql.yml.erb +2 -2
- data/lib/potassium/assets/config/database_postgresql.yml.erb +2 -2
- data/lib/potassium/assets/config/shrine.rb +33 -0
- data/lib/potassium/assets/docker-compose.ci.yml +1 -0
- data/lib/potassium/assets/lib/tasks/auto_annotate_models.rake +2 -1
- data/lib/potassium/assets/package.json +4 -1
- data/lib/potassium/cli/commands/create.rb +1 -0
- data/lib/potassium/cli_options.rb +6 -6
- data/lib/potassium/helpers/template-helpers.rb +4 -0
- data/lib/potassium/recipes/admin.rb +3 -3
- data/lib/potassium/recipes/annotate.rb +1 -1
- data/lib/potassium/recipes/ci.rb +1 -1
- data/lib/potassium/recipes/database_container.rb +5 -4
- data/lib/potassium/recipes/draper.rb +1 -1
- data/lib/potassium/recipes/file_storage.rb +15 -33
- data/lib/potassium/recipes/front_end.rb +128 -5
- data/lib/potassium/recipes/mailer.rb +5 -2
- data/lib/potassium/recipes/node.rb +21 -0
- data/lib/potassium/recipes/rack_cors.rb +18 -15
- data/lib/potassium/recipes/schedule.rb +1 -1
- data/lib/potassium/recipes/style.rb +21 -3
- data/lib/potassium/recipes/vue_admin.rb +124 -0
- data/lib/potassium/templates/application.rb +4 -2
- data/lib/potassium/version.rb +4 -3
- data/potassium.gemspec +6 -5
- data/spec/features/database_container_spec.rb +1 -1
- data/spec/features/file_storage_spec.rb +12 -16
- data/spec/features/front_end_spec.rb +74 -0
- data/spec/features/new_project_spec.rb +1 -1
- data/spec/features/node_spec.rb +28 -0
- data/spec/features/power_types_spec.rb +5 -16
- data/spec/features/vue_admin_spec.rb +47 -0
- data/spec/support/potassium_test_helpers.rb +23 -9
- metadata +56 -29
- data/lib/potassium/assets/.circleci/config.yml +0 -20
- data/lib/potassium/assets/active_admin/active_admin.js.coffee +0 -4
- data/lib/potassium/assets/active_admin/init_activeadmin_angular.rb +0 -8
- data/lib/potassium/assets/testing/paperclip.rb +0 -59
- data/lib/potassium/recipes/angular_admin.rb +0 -56
- data/spec/features/front_end.rb +0 -33
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"rules": {
|
3
|
+
"declaration-bang-space-before": "always",
|
4
|
+
"declaration-bang-space-after": "never",
|
5
|
+
"declaration-property-value-blacklist": {
|
6
|
+
"/^border/": ["none"]
|
7
|
+
},
|
8
|
+
"color-named": "never",
|
9
|
+
"declaration-block-no-duplicate-properties": true,
|
10
|
+
"rule-empty-line-before": ["always-multi-line", {
|
11
|
+
"except": ["after-single-line-comment", "first-nested"]
|
12
|
+
}],
|
13
|
+
"block-no-empty": true,
|
14
|
+
"no-missing-end-of-source-newline": true,
|
15
|
+
"color-hex-length": "short",
|
16
|
+
"color-hex-case": "lower",
|
17
|
+
"color-no-invalid-hex": true,
|
18
|
+
"selector-max-id": 0,
|
19
|
+
"declaration-no-important": true,
|
20
|
+
"indentation": 2,
|
21
|
+
"number-leading-zero": "never",
|
22
|
+
"no-duplicate-selectors": true,
|
23
|
+
"max-nesting-depth": 3,
|
24
|
+
"selector-pseudo-element-colon-notation": "double",
|
25
|
+
"selector-no-qualifying-type": true,
|
26
|
+
"shorthand-property-no-redundant-values": true,
|
27
|
+
"declaration-block-semicolon-newline-after": "always-multi-line",
|
28
|
+
"selector-list-comma-newline-after": "always",
|
29
|
+
"function-comma-space-after": "always-single-line",
|
30
|
+
"declaration-colon-space-after": "always",
|
31
|
+
"declaration-colon-space-before": "never",
|
32
|
+
"block-opening-brace-space-before": "always",
|
33
|
+
"function-parentheses-space-inside": "never",
|
34
|
+
"string-quotes": "single",
|
35
|
+
"declaration-block-trailing-semicolon": "always",
|
36
|
+
"no-eol-whitespace": true,
|
37
|
+
"number-no-trailing-zeros": true,
|
38
|
+
"function-url-quotes": "always",
|
39
|
+
"property-no-vendor-prefix": true,
|
40
|
+
"selector-no-vendor-prefix": true,
|
41
|
+
"media-feature-name-no-vendor-prefix": true,
|
42
|
+
"at-rule-no-vendor-prefix": true,
|
43
|
+
"value-no-vendor-prefix": true,
|
44
|
+
"length-zero-no-unit": true
|
45
|
+
}
|
46
|
+
}
|
@@ -1,7 +1,4 @@
|
|
1
|
-
PROJECT ?= <%= get(:
|
2
|
-
DOCKER_COMPOSE_FILE ?= docker-compose.yml
|
3
|
-
|
4
|
-
DOCKER_COMPOSE_ARGS ?= -p $(PROJECT) -f $(DOCKER_COMPOSE_FILE)
|
1
|
+
PROJECT ?= <%= get(:dasherized_app_name) %>
|
5
2
|
|
6
3
|
SHELL := /bin/bash
|
7
4
|
|
@@ -11,39 +8,16 @@ BOLD ?= $(shell tput bold)
|
|
11
8
|
NORMAL ?= $(shell tput sgr0)
|
12
9
|
|
13
10
|
help:
|
14
|
-
@echo
|
15
|
-
@echo " ${BOLD}make
|
16
|
-
@echo ""
|
17
|
-
@echo Runing the services like mysql:
|
18
|
-
@echo " ${BOLD}make services-up${NORMAL}"
|
11
|
+
@echo "Generate a backup in the environment (staging|production) database:"
|
12
|
+
@echo " ${BOLD}make backup-<environment>${NORMAL}"
|
19
13
|
@echo ""
|
20
|
-
@echo "
|
21
|
-
@echo " ${BOLD}make
|
14
|
+
@echo "Copy latest database backup from the environment (staging|production) to local database:"
|
15
|
+
@echo " ${BOLD}make restore-from-<environment>${NORMAL}"
|
22
16
|
@echo ""
|
23
17
|
|
24
|
-
setup:
|
25
|
-
bin/setup
|
26
|
-
|
27
|
-
services: services-up
|
28
|
-
|
29
|
-
services-ps:
|
30
|
-
docker-compose $(DOCKER_COMPOSE_ARGS) ps
|
31
|
-
|
32
|
-
services-up:
|
33
|
-
docker-compose $(DOCKER_COMPOSE_ARGS) up -d
|
34
|
-
|
35
|
-
services-stop:
|
36
|
-
docker-compose $(DOCKER_COMPOSE_ARGS) stop
|
37
|
-
|
38
|
-
services-down:
|
39
|
-
docker-compose $(DOCKER_COMPOSE_ARGS) down --volumes
|
40
|
-
|
41
|
-
services-logs:
|
42
|
-
docker-compose $(DOCKER_COMPOSE_ARGS) logs -f
|
43
|
-
|
44
18
|
services-port:
|
45
19
|
@set -o pipefail; \
|
46
|
-
docker-compose
|
20
|
+
docker-compose port ${SERVICE} ${PORT} 2> /dev/null | cut -d':' -f2 || echo ${PORT}
|
47
21
|
|
48
22
|
backup-staging: ROLE=staging
|
49
23
|
backup-production: ROLE=production
|
@@ -22,6 +22,20 @@ readme:
|
|
22
22
|
$ heroku local
|
23
23
|
|
24
24
|
[Heroku Local]: https://devcenter.heroku.com/articles/heroku-local
|
25
|
+
webpack:
|
26
|
+
title: "Development"
|
27
|
+
body: |
|
28
|
+
For hot-reloading and fast webpacker compilation you need to run webpack's dev server along with the rails server:
|
29
|
+
|
30
|
+
$ ./bin/webpack-dev-server
|
31
|
+
|
32
|
+
Running the dev server will also solve problems with the cache not refreshing between changes and provide better error messages if something fails to compile.
|
33
|
+
|
34
|
+
For even faster in-place component refreshing (with no page reloads), you can enable Hot Module Reloading in `config/webpacker.yml`
|
35
|
+
|
36
|
+
development:
|
37
|
+
dev_server:
|
38
|
+
hmr: true
|
25
39
|
ci:
|
26
40
|
title: "Continuous Integrations"
|
27
41
|
body: |
|
@@ -61,10 +75,17 @@ readme:
|
|
61
75
|
style_guide:
|
62
76
|
title: "Style Guides"
|
63
77
|
body: |
|
64
|
-
|
65
|
-
|
78
|
+
Style guides are enforced through a CircleCI [job](.circleci/config.yml) with [reviewdog](https://github.com/reviewdog/reviewdog) as a reporter, using per-project dependencies and style configurations.
|
79
|
+
Please note that this reviewdog implementation requires a GitHub user token to comment on pull requests. A token can be generated [here](https://github.com/settings/tokens), and it should have at least the `repo` option checked.
|
80
|
+
The included `config.yml` assumes your CircleCI organization has a context named `org-global` with the required token under the environment variable `REVIEWDOG_GITHUB_API_TOKEN`.
|
81
|
+
|
82
|
+
The project comes bundled with configuration files available in this repository.
|
83
|
+
|
84
|
+
Linting dependencies like `rubocop` or `rubocop-rspec` must be locked in your `Gemfile`. Similarly, packages like `eslint` or `eslint-plugin-vue` must be locked in your `package.json`.
|
85
|
+
|
86
|
+
You can add or modify rules by editing the [`.rubocop.yml`](.rubocop.yml), [`.eslintrc.json`](.eslintrc.json) or [`.stylelintrc.json`](.stylelintrc.json) files.
|
66
87
|
|
67
|
-
You can
|
88
|
+
You can (and should) use linter integrations for your text editor of choice, using the project's configuration.
|
68
89
|
mailing:
|
69
90
|
title: "Sending Emails"
|
70
91
|
body: |
|
@@ -82,12 +103,12 @@ readme:
|
|
82
103
|
devise:
|
83
104
|
title: "Authentication"
|
84
105
|
body: "We are using the great [Devise](https://github.com/plataformatec/devise) library by [PlataformaTec](http://plataformatec.com.br/)"
|
85
|
-
paperclip:
|
86
|
-
title: "Uploads"
|
87
|
-
body: "For managing uploads, this project uses [Paperclip](https://github.com/thoughtbot/paperclip), a gem made by the awesome [Thoughbot](https://thoughtbot.com/) team."
|
88
106
|
active_storage:
|
89
|
-
title: "
|
107
|
+
title: "File Storage"
|
90
108
|
body: "For managing uploads, this project uses [Active Storage](https://github.com/rails/rails/tree/master/activestorage)."
|
109
|
+
shrine:
|
110
|
+
title: "File Storage"
|
111
|
+
body: "For managing uploads, this project uses [Shrine](https://github.com/shrinerb/shrine)."
|
91
112
|
pundit:
|
92
113
|
title: "Authorization"
|
93
114
|
body: "For defining which parts of the system each user has access to, we have chosen to include the [Pundit](https://github.com/elabs/pundit) gem, by [Elabs](http://elabs.se/)."
|
@@ -109,6 +130,29 @@ readme:
|
|
109
130
|
power_types:
|
110
131
|
title: "Rails pattern enforcing types"
|
111
132
|
body: "This projects uses [Power-Types](https://github.com/platanus/power-types) to generate Services, Commands, Utils and Values."
|
133
|
+
active_admin:
|
134
|
+
title: "Administration"
|
135
|
+
body: |
|
136
|
+
This project uses [Active Admin](https://github.com/activeadmin/activeadmin) which is a Ruby on Rails framework for creating elegant backends for website administration.
|
137
|
+
<% if get(:vue_admin) %>
|
138
|
+
This project supports Vue inside ActiveAdmin
|
139
|
+
- The main package is located in `app/javascript/packs/admin_application.js`, here you will declare the components you want to include in your ActiveAdmin views as you would in a normal Vue App.
|
140
|
+
- Additionally, to be able to use Vue components as [Arbre](https://github.com/activeadmin/arbre) Nodes the component names are also declared in `config/initializers/active_admin.rb`
|
141
|
+
- The generator includes an example component called `admin_component`, you can use this component inside any ActiveAdmin view by just writing `admin_component` as you would with any `html` tag.
|
142
|
+
- For example:
|
143
|
+
```
|
144
|
+
admin_component(class:"myCustomClass",id:"myCustomId") do
|
145
|
+
admin_component(id:"otherCustomId")
|
146
|
+
end
|
147
|
+
```
|
148
|
+
- (Keep in mind that the example works with ruby blocks because `AdminComponent` has a `<slot>` tag defined, therefore children can be added to the component)
|
149
|
+
- The integration supports passing props to the components and converts them to their corresponing javascript objects.
|
150
|
+
- For example, the following works
|
151
|
+
```
|
152
|
+
admin_component(testList:[1,2,3,4],testObject:{"name":"Vue component"})
|
153
|
+
```
|
154
|
+
- You can also use **any** vue bindings such as `v-for` , `:key` etc.
|
155
|
+
<% end %>
|
112
156
|
seeds:
|
113
157
|
title: "Seeds"
|
114
158
|
body: |
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
I am a Vue Component {{ test }} {{ message }}
|
4
|
+
<slot />
|
5
|
+
</div>
|
6
|
+
</template>
|
7
|
+
|
8
|
+
<script>
|
9
|
+
export default {
|
10
|
+
props: {
|
11
|
+
test: {
|
12
|
+
type: String,
|
13
|
+
default: '',
|
14
|
+
},
|
15
|
+
testNumber: {
|
16
|
+
type: Number,
|
17
|
+
default: 0,
|
18
|
+
},
|
19
|
+
testObject: {
|
20
|
+
type: Object,
|
21
|
+
default: null,
|
22
|
+
},
|
23
|
+
testList: {
|
24
|
+
type: Array,
|
25
|
+
default: null,
|
26
|
+
},
|
27
|
+
},
|
28
|
+
|
29
|
+
data() {
|
30
|
+
return {
|
31
|
+
message: 'Hello World',
|
32
|
+
};
|
33
|
+
},
|
34
|
+
};
|
35
|
+
</script>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import Vue from 'vue/dist/vue.esm';
|
2
|
+
import AdminComponent from '../components/admin-component';
|
3
|
+
|
4
|
+
Vue.component('admin_component', AdminComponent);
|
5
|
+
|
6
|
+
document.addEventListener('DOMContentLoaded', () => {
|
7
|
+
if (document.getElementById('wrapper') !== null) {
|
8
|
+
return new Vue({
|
9
|
+
el: '#wrapper',
|
10
|
+
});
|
11
|
+
}
|
12
|
+
|
13
|
+
return null;
|
14
|
+
});
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
2
|
+
import App from 'app';
|
3
|
+
|
4
|
+
describe('App', () => {
|
5
|
+
test('is a Vue instance', () => {
|
6
|
+
const wrapper = shallowMount(App);
|
7
|
+
expect(wrapper.isVueInstance()).toBeTruthy();
|
8
|
+
});
|
9
|
+
|
10
|
+
it('displays message on load', () => {
|
11
|
+
const wrapper = shallowMount(App);
|
12
|
+
expect(wrapper.find('p').text()).toEqual('Hello Vue!');
|
13
|
+
});
|
14
|
+
});
|
@@ -44,6 +44,12 @@ dependencies(){
|
|
44
44
|
docker-compose $DOCKER_COMPOSE_ARGS run --rm test bundle install
|
45
45
|
}
|
46
46
|
|
47
|
+
<% if selected?(:front_end, :vue) %>
|
48
|
+
yarn_dependencies(){
|
49
|
+
docker-compose $DOCKER_COMPOSE_ARGS run --rm test yarn install
|
50
|
+
}
|
51
|
+
<% end %>
|
52
|
+
|
47
53
|
assets() {
|
48
54
|
docker-compose $DOCKER_COMPOSE_ARGS run --rm test /bin/bash -c "bin/setup && bundle exec rake assets:precompile"
|
49
55
|
}
|
@@ -62,6 +68,12 @@ tests(){
|
|
62
68
|
docker-compose $DOCKER_COMPOSE_ARGS run --rm test bundle exec rspec spec $RSPEC_FORMAT_ARGS $RSPEC_JUNIT_ARGS
|
63
69
|
}
|
64
70
|
|
71
|
+
<% if selected?(:front_end, :vue) %>
|
72
|
+
js_tests(){
|
73
|
+
docker-compose $DOCKER_COMPOSE_ARGS run --rm test yarn run test
|
74
|
+
}
|
75
|
+
<% end %>
|
76
|
+
|
65
77
|
# Run the complete ci build
|
66
78
|
no_ci(){
|
67
79
|
build
|
@@ -80,7 +92,7 @@ case "$1" in
|
|
80
92
|
wait_services
|
81
93
|
;;
|
82
94
|
"deps"|"dependencies")
|
83
|
-
dependencies
|
95
|
+
dependencies <% if selected?(:front_end, :vue) %>&& yarn_dependencies<% end %>
|
84
96
|
;;
|
85
97
|
"assets")
|
86
98
|
assets
|
@@ -88,6 +100,11 @@ case "$1" in
|
|
88
100
|
"db"|"database")
|
89
101
|
database
|
90
102
|
;;
|
103
|
+
<% if selected?(:front_end, :vue) %>
|
104
|
+
"js_tests")
|
105
|
+
js_tests
|
106
|
+
;;
|
107
|
+
<% end %>
|
91
108
|
"specs"|"tests")
|
92
109
|
tests
|
93
110
|
;;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
development: &default
|
2
2
|
adapter: mysql2
|
3
|
-
database: <%= get(:
|
3
|
+
database: <%= get(:dasherized_app_name) %>_development
|
4
4
|
encoding: utf8
|
5
5
|
host: <%%= ENV["DB_HOST"] || "127.0.0.1" %>
|
6
6
|
port: <%%= ENV["DB_PORT"] || 3306 %>
|
@@ -12,7 +12,7 @@ development: &default
|
|
12
12
|
|
13
13
|
test:
|
14
14
|
<<: *default
|
15
|
-
database: <%= get(:
|
15
|
+
database: <%= get(:dasherized_app_name) %>_test
|
16
16
|
|
17
17
|
production: &deploy
|
18
18
|
encoding: utf8
|
@@ -1,6 +1,6 @@
|
|
1
1
|
development: &default
|
2
2
|
adapter: postgresql
|
3
|
-
database: <%= get(:
|
3
|
+
database: <%= get(:dasherized_app_name) %>_development
|
4
4
|
encoding: utf8
|
5
5
|
host: <%%= ENV["DB_HOST"] || "127.0.0.1" %>
|
6
6
|
port: <%%= ENV["DB_PORT"] || 5432 %>
|
@@ -12,7 +12,7 @@ development: &default
|
|
12
12
|
|
13
13
|
test:
|
14
14
|
<<: *default
|
15
|
-
database: <%= get(:
|
15
|
+
database: <%= get(:dasherized_app_name) %>_test
|
16
16
|
|
17
17
|
production: &deploy
|
18
18
|
encoding: utf8
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'shrine'
|
2
|
+
|
3
|
+
if Rails.env.development?
|
4
|
+
require 'shrine/storage/file_system'
|
5
|
+
|
6
|
+
Shrine.storages = {
|
7
|
+
cache: Shrine::Storage::FileSystem.new('public', prefix: 'uploads/cache'),
|
8
|
+
store: Shrine::Storage::FileSystem.new('public', prefix: 'uploads')
|
9
|
+
}
|
10
|
+
elsif Rails.env.production?
|
11
|
+
require 'shrine/storage/s3'
|
12
|
+
|
13
|
+
s3_options = {
|
14
|
+
bucket: ENV.fetch('S3_BUCKET'),
|
15
|
+
region: ENV.fetch('AWS_REGION'),
|
16
|
+
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
|
17
|
+
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY')
|
18
|
+
}
|
19
|
+
|
20
|
+
Shrine.storages = {
|
21
|
+
cache: Shrine::Storage::S3.new(prefix: 'cache', **s3_options),
|
22
|
+
store: Shrine::Storage::S3.new(**s3_options)
|
23
|
+
}
|
24
|
+
else
|
25
|
+
require 'shrine/storage/memory'
|
26
|
+
|
27
|
+
Shrine.storages[:store] = Shrine::Storage::Memory.new
|
28
|
+
end
|
29
|
+
|
30
|
+
Shrine.plugin :activerecord
|
31
|
+
Shrine.plugin :cached_attachment_data
|
32
|
+
Shrine.plugin :restore_cached_data
|
33
|
+
Shrine.plugin :determine_mime_type, analyzer: :marcel
|