potassium 6.5.0 → 6.6.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/CHANGELOG.md +20 -0
- data/README.md +30 -1
- data/docs/CONTRIBUTING.md +2 -2
- data/lib/potassium/assets/.circleci/config.yml.erb +11 -1
- data/lib/potassium/assets/.eslintrc.json +15 -9
- data/lib/potassium/assets/.rubocop.yml +1 -0
- data/lib/potassium/assets/Aptfile +5 -0
- data/lib/potassium/assets/README.yml +30 -6
- data/lib/potassium/assets/active_admin/admin-component.vue +22 -30
- data/lib/potassium/assets/app/javascript/{app.spec.js → components/app.spec.ts} +1 -1
- data/lib/potassium/assets/app/javascript/components/app.vue +9 -0
- data/lib/potassium/assets/app/javascript/types/vue.d.ts +5 -0
- data/lib/potassium/assets/app/jobs/shrine_promote_job.rb +14 -0
- data/lib/potassium/assets/app/mailers/application_mailer.rb +1 -1
- data/lib/potassium/assets/app/mailers/example_mailer.rb +6 -0
- data/lib/potassium/assets/app/serializers/base_serializer.rb +3 -0
- data/lib/potassium/assets/app/serializers/concerns/image_handling_attributes.rb +20 -0
- data/lib/potassium/assets/app/uploaders/cover_image_uploader.rb +52 -0
- data/lib/potassium/assets/app/views/example_mailer/example_mail.html.mjml +7 -0
- data/lib/potassium/assets/app/views/layouts/default_mail.html.mjml +49 -0
- data/lib/potassium/assets/config/initializers/shrine/plugins/image_handling_utilities.rb +143 -0
- data/lib/potassium/assets/config/mailer.rb.erb +0 -2
- data/lib/potassium/assets/config/shrine.rb +15 -0
- data/lib/potassium/assets/config/webpack/rules/css.js +5 -0
- data/lib/potassium/assets/config/webpack/rules/index.js +11 -0
- data/lib/potassium/assets/config/webpack/rules/jquery.js +11 -0
- data/lib/potassium/assets/config/webpack/rules/typescript.js +32 -0
- data/lib/potassium/assets/config/webpack/rules/vue.js +19 -0
- data/lib/potassium/assets/config/webpack/webpack.config.js +4 -0
- data/lib/potassium/assets/public/mails/platanus-logo.png +0 -0
- data/lib/potassium/assets/tsconfig.json +31 -0
- data/lib/potassium/cli/commands/create.rb +3 -1
- data/lib/potassium/cli_options.rb +15 -3
- data/lib/potassium/platanus_config.rb +20 -0
- data/lib/potassium/recipes/admin.rb +11 -0
- data/lib/potassium/recipes/api.rb +6 -85
- data/lib/potassium/recipes/coverage.rb +31 -0
- data/lib/potassium/recipes/file_storage.rb +50 -0
- data/lib/potassium/recipes/front_end.rb +82 -110
- data/lib/potassium/recipes/google_tag_manager.rb +1 -1
- data/lib/potassium/recipes/mailer.rb +22 -10
- data/lib/potassium/recipes/mjml.rb +31 -0
- data/lib/potassium/recipes/node.rb +11 -13
- data/lib/potassium/recipes/style.rb +9 -2
- data/lib/potassium/recipes/vue_admin.rb +38 -8
- data/lib/potassium/templates/application.rb +1 -0
- data/lib/potassium/version.rb +8 -3
- data/spec/features/api_spec.rb +6 -1
- data/spec/features/coverage_spec.rb +17 -0
- data/spec/features/file_storage_spec.rb +102 -26
- data/spec/features/front_end_spec.rb +14 -48
- data/spec/features/mailer_spec.rb +79 -33
- data/spec/features/mjml_spec.rb +53 -0
- data/spec/features/vue_admin_spec.rb +0 -10
- data/spec/support/shared_examples.rb +5 -0
- metadata +28 -21
- data/lib/potassium/assets/active_admin/admin_application.js +0 -14
- data/lib/potassium/assets/active_admin/init_activeadmin_vue.rb +0 -10
- data/lib/potassium/assets/app/graphql/graphql_controller.rb +0 -55
- data/lib/potassium/assets/app/graphql/mutations/login_mutation.rb +0 -23
- data/lib/potassium/assets/app/graphql/queries/base_query.rb +0 -4
- data/lib/potassium/assets/app/graphql/types/base/base_argument.rb +0 -4
- data/lib/potassium/assets/app/graphql/types/base/base_enum.rb +0 -4
- data/lib/potassium/assets/app/graphql/types/base/base_field.rb +0 -5
- data/lib/potassium/assets/app/graphql/types/base/base_input_object.rb +0 -5
- data/lib/potassium/assets/app/graphql/types/base/base_interface.rb +0 -7
- data/lib/potassium/assets/app/graphql/types/base/base_object.rb +0 -5
- data/lib/potassium/assets/app/graphql/types/base/base_scalar.rb +0 -4
- data/lib/potassium/assets/app/graphql/types/base/base_union.rb +0 -4
- data/lib/potassium/assets/app/graphql/types/mutation_type.rb +0 -10
- data/lib/potassium/assets/app/graphql/types/query_type.rb +0 -13
- data/lib/potassium/assets/config/graphql_playground.rb +0 -20
- data/spec/features/graphql_spec.rb +0 -71
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0bc57ea8c0f92d1ce3dd15feef9164f7bef381ce322051bd810a3303c8ca257c
|
|
4
|
+
data.tar.gz: f31b33309764331c194d97380a37ccd0afdfa50ccd38eeba7931e330262179c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c88f8cd6cb7f6814233c608c05aabb77369ab11887a64256efbba4e813c8cf1d2ee9c4fffc3ca9c45e24618b70e8e652318969cd38f50d7741888e06bdde1333
|
|
7
|
+
data.tar.gz: 788dbd755914cae98ca2bbd6c4f3566deacdf8eccba0a0b50eaff92facbc95b31bd23ec31a9a4026e0643dfe9fa0a8a888b3c962dd3cc557c184b3d69f245a54
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 6.6.0
|
|
6
|
+
Features
|
|
7
|
+
- Update power api gem to use v2.0.0. Install "internal" API mode [#394](https://github.com/platanus/potassium/pull/394)
|
|
8
|
+
- Updates Webpacker to Shakapacker, upgrading Vue and TailwindCSS to their latest versions [#395](https://github.com/platanus/potassium/pull/395)
|
|
9
|
+
- Add some image handling and processing in shrine file storage option [#398](https://github.com/platanus/potassium/pull/398)
|
|
10
|
+
- Include `--platanus-config` option to skip most of the instalation options [#399](https://github.com/platanus/potassium/pull/399).
|
|
11
|
+
- Add [`rubocop-platanus`](https://github.com/platanus/rubocop-platanus) gem for linting platanus' best practices [#402](https://github.com/platanus/potassium/pull/402).
|
|
12
|
+
- Remove graphql option [#404](https://github.com/platanus/potassium/pull/404)
|
|
13
|
+
- Add frontend testing coverage for Jest [#401](https://github.com/platanus/potassium/pull/401) and associated reviewdog comments [#406](https://github.com/platanus/potassium/pull/406)
|
|
14
|
+
- Add MJML to handle mail templates, with example [#405](https://github.com/platanus/potassium/pull/405)
|
|
15
|
+
|
|
16
|
+
Fixes
|
|
17
|
+
- Add missing vips CI config when selecting shrine [#403](https://github.com/platanus/potassium/pull/403).
|
|
18
|
+
- Fix shakapacker to version 6.2.x to avoid [this bug](https://github.com/shakacode/shakapacker/issues/123) [#404](https://github.com/platanus/potassium/pull/404)
|
|
19
|
+
|
|
3
20
|
## 6.5.0
|
|
4
21
|
|
|
5
22
|
Features
|
|
@@ -9,9 +26,12 @@ Features
|
|
|
9
26
|
- Add SimpleCov recipe [#387](https://github.com/platanus/potassium/pull/387)
|
|
10
27
|
- Update Rails to 6.1 [#389](https://github.com/platanus/potassium/pull/389) & [#392](https://github.com/platanus/potassium/pull/392)
|
|
11
28
|
- Include `run_test` as a valid example group [#379](https://github.com/platanus/potassium/pull/379). This was added incorrectly in this [PR](https://github.com/platanus/potassium/pull/379).
|
|
29
|
+
- Add system tests configuration [#388](https://github.com/platanus/potassium/pull/388)
|
|
30
|
+
- Allow CircleCI cache clearing [#383](https://github.com/platanus/potassium/pull/383)
|
|
12
31
|
|
|
13
32
|
Fixes
|
|
14
33
|
- Remove rails_stdout_logging gem because it is no longer needed after Rails 5 and it was generating a deprecation warning [#325](https://github.com/platanus/potassium/pull/325)
|
|
34
|
+
- Fix default action dissapearance when using `binding.pry` in generated projects [#385](https://github.com/platanus/potassium/pull/385)
|
|
15
35
|
|
|
16
36
|
## 6.4.0
|
|
17
37
|
|
data/README.md
CHANGED
|
@@ -21,6 +21,34 @@ Use the `potassium create` command to create a new project:
|
|
|
21
21
|
> 2. If you feel that it's too slow, you may need to update rubygems: `gem update --system`.
|
|
22
22
|
> 3. Potassium uses node under the hood, so a check will also be performed to ensure you are running the supported version.
|
|
23
23
|
|
|
24
|
+
#### Platanus Configutarion
|
|
25
|
+
|
|
26
|
+
In case you want to use the Platanus Configuration you should use the following command:
|
|
27
|
+
|
|
28
|
+
$ potassium create <project-name> --platanus-config
|
|
29
|
+
|
|
30
|
+
This will create a project with the following configuration:
|
|
31
|
+
1. `database`: `'postgresql'`
|
|
32
|
+
2. `local`: `'es-CL'`
|
|
33
|
+
3. `email_service`: `'sendgrid'`
|
|
34
|
+
4. `devise`: `true`
|
|
35
|
+
5. `devise-user-model`: `true`
|
|
36
|
+
6. `admin`: `true`
|
|
37
|
+
7. `vue_admin`: `true`
|
|
38
|
+
8. `pundit`: `true`
|
|
39
|
+
9. `api`: `true`
|
|
40
|
+
10. `storage`: `'shrine'`
|
|
41
|
+
11. `heroku`: `true`
|
|
42
|
+
12. `background_processor`: `true`
|
|
43
|
+
13. `draper`: `true`
|
|
44
|
+
14. `schedule`: `true`
|
|
45
|
+
15. `sentry`: `true`
|
|
46
|
+
16. `front_end`: `'vue'`
|
|
47
|
+
17. `google_tag_manager`: `true`
|
|
48
|
+
18. `test`: `true`
|
|
49
|
+
19. `spring`: `true`
|
|
50
|
+
|
|
51
|
+
The remaining question will be asked as usual.
|
|
24
52
|
### Adding recipes to an existing project
|
|
25
53
|
|
|
26
54
|
Use the `potassium install` command to add a recipe to a project:
|
|
@@ -53,6 +81,7 @@ Potassium Rails apps includes the following gems and technologies:
|
|
|
53
81
|
- [Tzinfo-Data](https://github.com/tzinfo/tzinfo-data) for updating timezone information
|
|
54
82
|
- [Faker](https://github.com/stympy/faker) for creating development data
|
|
55
83
|
- [Scout](https://github.com/scoutapp/scout_apm_ruby) for monitoring performance
|
|
84
|
+
- [Mjml](https://github.com/sighmon/mjml-rails) for mails style
|
|
56
85
|
|
|
57
86
|
The following optional integrations are also added:
|
|
58
87
|
|
|
@@ -177,4 +206,4 @@ potassium is maintained by [platanus](http://platan.us).
|
|
|
177
206
|
|
|
178
207
|
## License
|
|
179
208
|
|
|
180
|
-
Potassium is © 2014 Platanus, SPA. It is free software and may be redistributed under the terms specified in the LICENSE file.
|
|
209
|
+
Potassium is © 2014 Platanus, SPA. It is free software and may be redistributed under the terms specified in the [LICENSE](/LICENSE.txt) file.
|
data/docs/CONTRIBUTING.md
CHANGED
|
@@ -54,7 +54,7 @@ This method is used if you need to ask something to the user before doing someth
|
|
|
54
54
|
```ruby
|
|
55
55
|
def ask
|
|
56
56
|
use_banana_split = answer(:banana_split) do
|
|
57
|
-
Ask.confirm("Do you
|
|
57
|
+
Ask.confirm("Do you want to use Banana Split?")
|
|
58
58
|
end
|
|
59
59
|
set(:use_banana_split, true) if use_banana_split
|
|
60
60
|
end
|
|
@@ -103,7 +103,7 @@ For example if you run `portassium install devise` this will use
|
|
|
103
103
|
[the recipe template](/lib/potassium/templates/recipe.rb) to load an execute the
|
|
104
104
|
`install` method for the **devise** recipe.
|
|
105
105
|
|
|
106
|
-
You can
|
|
106
|
+
You can define the main functionallity of a recipe in a private method and call
|
|
107
107
|
it from the `create` and `install` methods.
|
|
108
108
|
|
|
109
109
|
```ruby
|
|
@@ -78,6 +78,13 @@ commands:
|
|
|
78
78
|
key: yarn-dependencies-{{ .Environment.YARN_CACHE_VERSION }}-{{ checksum "yarn.lock" }}
|
|
79
79
|
paths:
|
|
80
80
|
- node_modules
|
|
81
|
+
<%- if selected?(:storage, :shrine) -%>
|
|
82
|
+
- run:
|
|
83
|
+
name: Install apt and vips buildpack dependencies
|
|
84
|
+
command: |
|
|
85
|
+
xargs -a Aptfile sudo apt-get install
|
|
86
|
+
sudo apt-get install libvips
|
|
87
|
+
<%- end -%>
|
|
81
88
|
|
|
82
89
|
jobs:
|
|
83
90
|
test:
|
|
@@ -125,7 +132,10 @@ jobs:
|
|
|
125
132
|
<%- if selected?(:front_end, :vue) -%>
|
|
126
133
|
- run:
|
|
127
134
|
name: Run jest
|
|
128
|
-
command:
|
|
135
|
+
command: |
|
|
136
|
+
yarn run test > coverage/input_jest.txt
|
|
137
|
+
./node_modules/.bin/format-coverage coverage/input_jest.txt coverage/output_jest.txt /home/circleci/project/app/javascript
|
|
138
|
+
cat coverage/output_jest.txt | ./bin/reviewdog -reporter=github-pr-review -efm="%f:%l:%c: %m"
|
|
129
139
|
<%- end -%>
|
|
130
140
|
|
|
131
141
|
- store_test_results:
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"env": {
|
|
3
|
-
"
|
|
3
|
+
"browser": true,
|
|
4
|
+
"es2021": true,
|
|
5
|
+
"node": true,
|
|
6
|
+
"jest/globals": true,
|
|
7
|
+
"vue/setup-compiler-macros": true
|
|
4
8
|
},
|
|
5
9
|
"parserOptions": {
|
|
6
|
-
"ecmaVersion":
|
|
10
|
+
"ecmaVersion": 2020,
|
|
7
11
|
"sourceType": "module"
|
|
8
12
|
},
|
|
9
|
-
"plugins": ["import"],
|
|
13
|
+
"plugins": ["import", "jest", "tailwindcss"],
|
|
10
14
|
"settings": {
|
|
11
15
|
"import/resolver": {
|
|
12
16
|
"node": {
|
|
@@ -15,7 +19,10 @@
|
|
|
15
19
|
}
|
|
16
20
|
},
|
|
17
21
|
"extends": [
|
|
18
|
-
"plugin:vue/
|
|
22
|
+
"plugin:vue/vue3-recommended",
|
|
23
|
+
"@vue/typescript/recommended",
|
|
24
|
+
"@vue/eslint-config-typescript",
|
|
25
|
+
"plugin:tailwindcss/recommended"
|
|
19
26
|
],
|
|
20
27
|
"rules": {
|
|
21
28
|
"accessor-pairs": 0,
|
|
@@ -338,14 +345,13 @@
|
|
|
338
345
|
"vue/max-len": ["error", {
|
|
339
346
|
"code": 120,
|
|
340
347
|
"ignoreHTMLAttributeValues": true
|
|
341
|
-
|
|
348
|
+
}]
|
|
342
349
|
},
|
|
343
350
|
"overrides": [
|
|
344
351
|
{
|
|
345
|
-
"files": ["
|
|
346
|
-
"
|
|
347
|
-
|
|
348
|
-
"node": true
|
|
352
|
+
"files": ["*.ts", "*.vue"],
|
|
353
|
+
"rules": {
|
|
354
|
+
"no-undef": "off"
|
|
349
355
|
}
|
|
350
356
|
}
|
|
351
357
|
]
|
|
@@ -27,7 +27,7 @@ readme:
|
|
|
27
27
|
body: |
|
|
28
28
|
For hot-reloading and fast webpacker compilation you need to run webpack's dev server along with the rails server:
|
|
29
29
|
|
|
30
|
-
$ ./bin/
|
|
30
|
+
$ ./bin/webpacker-dev-server
|
|
31
31
|
|
|
32
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
33
|
|
|
@@ -105,7 +105,34 @@ readme:
|
|
|
105
105
|
body: "For managing uploads, this project uses [Active Storage](https://github.com/rails/rails/tree/master/activestorage)."
|
|
106
106
|
shrine:
|
|
107
107
|
title: "File Storage"
|
|
108
|
-
body:
|
|
108
|
+
body: |
|
|
109
|
+
For managing uploads, this project uses [Shrine](https://github.com/shrinerb/shrine). When generated, this project includes the following files and configurations:
|
|
110
|
+
|
|
111
|
+
- `ImageUploader` that includes file type validation
|
|
112
|
+
- `CoverImageUploader`, inheriting from `ImageUploader`. It does a couple of things:
|
|
113
|
+
- Generates derivatives in `jpg` and `webp` format, for three different sizes. For an attachment of name `image`, to get the url for a derivative, let's say `sm`, you would do `record.image_url(:sm)`
|
|
114
|
+
- Saves a [blurhash](https://blurha.sh/) code to the attachment metadata
|
|
115
|
+
- `ImageHandlingUtilities`, a shrine plugin in the initializers folder that is used in the `CoverImageUploader`. Given a model with an attachment of name `image`, it adds the following methods to the model:
|
|
116
|
+
- `image_blurhash`: returns blurhash from metadata
|
|
117
|
+
- `generate_image_derivatives`: It generates all derivatives defined in Uploader. If file already had derivatives, it replaces them with newly generated ones. Associated class method: `generate_all_image_derivatives`
|
|
118
|
+
- `generate_image_metadata`: refreshes all metadata for attachment. Associated class method: `generate_all_image_metadata`
|
|
119
|
+
- `generate_image_derivatives_and_metadata`: does both previous things. Useful because it does so opening the file only once. Associated class method: `generate_all_image_derivatives_and_metadata`
|
|
120
|
+
|
|
121
|
+
Class methods are the same as their instance counterparts, but for collections. They also allow error handling on an individual record by passing a block to handle each error. If no block is given, attachments that throw errors are ignored and the iteration continues
|
|
122
|
+
- `ImageHandlingAttributes` serializer concern. It adds a method `add_image_handling_attributes` to all serializers that inherit from `BaseSerializer`. Considering an attachment of name `image`, this method adds two attributes to the serialized record:
|
|
123
|
+
- `image_blurhash`
|
|
124
|
+
- `image`. This is a hash that includes urls for all derivatives passed to the method. For example:
|
|
125
|
+
```
|
|
126
|
+
add_image_handling_attributes(attachment_name: :image, derivatives: [:sm, :md], include_original_image: true)
|
|
127
|
+
|
|
128
|
+
# results in the following hash for the image attribute:
|
|
129
|
+
# {
|
|
130
|
+
# sm: { url: 'someurl.com/bla' },
|
|
131
|
+
# md: { url: 'someurl.com/ble' },
|
|
132
|
+
# original: { url: 'someurl.com/ble' }
|
|
133
|
+
# }
|
|
134
|
+
```
|
|
135
|
+
- `SHRINE_SECRET_KEY` environment variable. It comes witha value set in `.env.development`, but you'll need to set one for it in staging and production. It can be any random value, generating it with `SecureRandom.hex` for instance
|
|
109
136
|
pundit:
|
|
110
137
|
title: "Authorization"
|
|
111
138
|
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/)."
|
|
@@ -127,16 +154,13 @@ readme:
|
|
|
127
154
|
power_api:
|
|
128
155
|
title: "API Support"
|
|
129
156
|
body: "This projects uses [Power API](https://github.com/platanus/power_api). It's a Rails engine that gathers a set of gems and configurations designed to build incredible REST APIs."
|
|
130
|
-
graphql:
|
|
131
|
-
title: "API Support"
|
|
132
|
-
body: "This projects uses [graphql-ruby](https://graphql-ruby.org/) to generate a GraphQL API."
|
|
133
157
|
active_admin:
|
|
134
158
|
title: "Administration"
|
|
135
159
|
body: |
|
|
136
160
|
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
161
|
<% if get(:vue_admin) %>
|
|
138
162
|
This project supports Vue inside ActiveAdmin
|
|
139
|
-
- The main package is located in `app/javascript/
|
|
163
|
+
- The main package is located in `app/javascript/active_admin.js`, here you will declare the components you want to include in your ActiveAdmin views as you would in a normal Vue App.
|
|
140
164
|
- 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
165
|
- 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
166
|
- For example:
|
|
@@ -1,35 +1,27 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
test?: string
|
|
4
|
+
testNumber?: number
|
|
5
|
+
testObject?: {[key: string]: string},
|
|
6
|
+
testList?: number[],
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(
|
|
10
|
+
defineProps<Props>(),
|
|
11
|
+
{
|
|
12
|
+
test: undefined,
|
|
13
|
+
testNumber: 0,
|
|
14
|
+
testObject: undefined,
|
|
15
|
+
testList: undefined,
|
|
16
|
+
},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const message = 'Hello World';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
1
22
|
<template>
|
|
2
23
|
<div>
|
|
3
|
-
I am a Vue Component {{ test }} {{ message }}
|
|
24
|
+
I am a Vue Component {{ props.test }} {{ message }}
|
|
4
25
|
<slot />
|
|
5
26
|
</div>
|
|
6
27
|
</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
|
+
class ShrinePromoteJob < ApplicationJob
|
|
2
|
+
queue_as :default
|
|
3
|
+
|
|
4
|
+
def perform(attacher_class, record_class, record_id, name, file_data)
|
|
5
|
+
attacher_class = Object.const_get(attacher_class)
|
|
6
|
+
record = Object.const_get(record_class).find(record_id)
|
|
7
|
+
|
|
8
|
+
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
|
9
|
+
attacher.create_derivatives
|
|
10
|
+
attacher.atomic_promote
|
|
11
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
|
12
|
+
# attachment has changed or the record has been deleted, nothing to do
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module ImageHandlingAttributes
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
class_methods do
|
|
5
|
+
def add_image_handling_attributes(attachment_name:, derivatives:, include_original_image: false)
|
|
6
|
+
attributes attachment_name, "#{attachment_name}_blurhash".to_sym
|
|
7
|
+
|
|
8
|
+
define_method(attachment_name) do
|
|
9
|
+
attachment_hash = derivatives.reduce({}) do |hash, derivative|
|
|
10
|
+
hash[derivative] = { url: object.send("#{attachment_name}_url", derivative) }
|
|
11
|
+
hash
|
|
12
|
+
end
|
|
13
|
+
if include_original_image
|
|
14
|
+
attachment_hash[:original] = { url: object.send("#{attachment_name}_url") }
|
|
15
|
+
end
|
|
16
|
+
attachment_hash
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require "image_processing/vips"
|
|
2
|
+
|
|
3
|
+
class CoverImageUploader < ImageUploader
|
|
4
|
+
plugin :derivation_endpoint, prefix: "derivations/cover_image"
|
|
5
|
+
plugin :add_metadata
|
|
6
|
+
plugin :image_handling_utilities
|
|
7
|
+
|
|
8
|
+
DERIVATIVES = {
|
|
9
|
+
sm: { size: [426, 240], type: 'jpg' },
|
|
10
|
+
md: { size: [960, 540], type: 'jpg' },
|
|
11
|
+
lg: { size: [1280, 720], type: 'jpg' },
|
|
12
|
+
webp_sm: { size: [426, 240], type: 'webp' },
|
|
13
|
+
webp_md: { size: [960, 540], type: 'webp' },
|
|
14
|
+
webp_lg: { size: [1280, 720], type: 'webp' }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Attacher.derivatives do |original|
|
|
18
|
+
vips = ImageProcessing::Vips.source(original)
|
|
19
|
+
|
|
20
|
+
DERIVATIVES.reduce({}) do |derivatives_hash, (name, derivative_info)|
|
|
21
|
+
derivatives_hash[name] = vips.convert(derivative_info[:type]).resize_to_limit!(
|
|
22
|
+
*derivative_info[:size]
|
|
23
|
+
)
|
|
24
|
+
derivatives_hash
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
derivation :thumbnail do |file, width, height|
|
|
29
|
+
ImageProcessing::Vips
|
|
30
|
+
.source(file)
|
|
31
|
+
.resize_to_limit!(width.to_i, height.to_i)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
Attacher.default_url do |derivative: nil, **|
|
|
35
|
+
file&.derivation_url(:thumbnail, *DERIVATIVES.dig(derivative, :size)) if derivative.present?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
add_metadata :blurhash do |io, derivative: nil, **|
|
|
39
|
+
if derivative.nil?
|
|
40
|
+
Shrine.with_file(io) do |file|
|
|
41
|
+
image = Vips::Image.new_from_file(file.path, access: :sequential)
|
|
42
|
+
image = image.resize(100.0 / image.width)
|
|
43
|
+
flat_rgb_pixels = []
|
|
44
|
+
image.to_a.each do |row|
|
|
45
|
+
row.each { |pixel| flat_rgb_pixels.concat(pixel[0..2]) }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Blurhash.encode(image.width, image.height, flat_rgb_pixels)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<mjml>
|
|
2
|
+
<mj-head>
|
|
3
|
+
<mj-attributes>
|
|
4
|
+
<mj-all font-family="'Helvetica Neue', Helvetica, Arial, sans-serif"></mj-all>
|
|
5
|
+
<mj-text font-weight="400" font-size="16px" color="#000000" line-height="24px" font-family="'Helvetica Neue', Helvetica, Arial, sans-serif"></mj-text>
|
|
6
|
+
</mj-attributes>
|
|
7
|
+
<mj-style inline="inline">
|
|
8
|
+
.body-section {
|
|
9
|
+
-webkit-box-shadow: 1px 4px 11px 0px rgba(0, 0, 0, 0.15);
|
|
10
|
+
-moz-box-shadow: 1px 4px 11px 0px rgba(0, 0, 0, 0.15);
|
|
11
|
+
box-shadow: 1px 4px 11px 0px rgba(0, 0, 0, 0.15);
|
|
12
|
+
}
|
|
13
|
+
</mj-style>
|
|
14
|
+
<mj-style inline="inline">
|
|
15
|
+
.text-link {
|
|
16
|
+
color: #5e6ebf
|
|
17
|
+
}
|
|
18
|
+
</mj-style>
|
|
19
|
+
<mj-style inline="inline">
|
|
20
|
+
.footer-link {
|
|
21
|
+
color: #888888
|
|
22
|
+
}
|
|
23
|
+
</mj-style>
|
|
24
|
+
|
|
25
|
+
</mj-head>
|
|
26
|
+
<mj-body width="600px">
|
|
27
|
+
<mj-section full-width="full-width" background-color="#71717A" padding-bottom="0">
|
|
28
|
+
<mj-column width="100%" background-color="#A1A1AA">
|
|
29
|
+
<mj-spacer height="25px" />
|
|
30
|
+
</mj-column>
|
|
31
|
+
</mj-section>
|
|
32
|
+
<mj-section background-color="#A1A1AA" padding-bottom="0" padding-top="0">
|
|
33
|
+
<mj-column>
|
|
34
|
+
<mj-image width="100px" src="<%= image_url('/mails/platanus-logo.png') %>" align="center">
|
|
35
|
+
</mj-column>
|
|
36
|
+
<mj-column width="100%">
|
|
37
|
+
<mj-spacer height="25px" />
|
|
38
|
+
</mj-column>
|
|
39
|
+
</mj-section>
|
|
40
|
+
<mj-wrapper padding-top="0" padding-bottom="0" css-class="body-section" background-color="#ffffff" padding-left="15px" padding-right="15px">
|
|
41
|
+
<%= yield %>
|
|
42
|
+
</mj-wrapper>
|
|
43
|
+
<mj-section background-color="#A1A1AA" padding-bottom="0" padding-top="0">
|
|
44
|
+
<mj-column width="100%">
|
|
45
|
+
<mj-spacer height="25px" />
|
|
46
|
+
</mj-column>
|
|
47
|
+
</mj-section>
|
|
48
|
+
</mj-body>
|
|
49
|
+
</mjml>
|