yarii-cloudinary 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +34 -0
  4. data/Rakefile +32 -0
  5. data/app/controllers/yarii_cloudinary/application_controller.rb +6 -0
  6. data/app/controllers/yarii_cloudinary/media_controller.rb +33 -0
  7. data/app/helpers/yarii_cloudinary/application_helper.rb +9 -0
  8. data/app/javascript/controllers/cloudinary_browse_media_controller.js +21 -0
  9. data/app/javascript/controllers/cloudinary_multiple_media_controller.js +164 -0
  10. data/app/javascript/controllers/cloudinary_single_media_controller.js +73 -0
  11. data/app/javascript/controllers/index.js +11 -0
  12. data/app/javascript/packs/application.js +2 -0
  13. data/app/jobs/yarii_cloudinary/application_job.rb +4 -0
  14. data/app/styles/index.scss +43 -0
  15. data/app/views/yarii_cloudinary/application/yarii_cloudinary_head.erb +2 -0
  16. data/app/views/yarii_cloudinary/media/_browse_thumbnail.html.erb +3 -0
  17. data/app/views/yarii_cloudinary/media/_form_thumbnail.html.erb +3 -0
  18. data/app/views/yarii_cloudinary/media/_modal.html.erb +4 -0
  19. data/app/views/yarii_cloudinary/media/_multiple_form_item.html.erb +25 -0
  20. data/app/views/yarii_cloudinary/media/index.html.erb +22 -0
  21. data/app/views/yarii_editor/editor/_cloudinary.html.erb +42 -0
  22. data/app/views/yarii_editor/editor/_cloudinary_multiple.html.erb +50 -0
  23. data/config/routes.rb +8 -0
  24. data/config/webpack/development.js +5 -0
  25. data/config/webpack/environment.js +3 -0
  26. data/config/webpack/production.js +5 -0
  27. data/config/webpack/staging.js +5 -0
  28. data/config/webpack/test.js +5 -0
  29. data/config/webpacker.yml +110 -0
  30. data/db/migrate/20190923000809_create_yarii_sites.rb +12 -0
  31. data/lib/tasks/yarii_cloudinary_tasks.rake +61 -0
  32. data/lib/yarii-cloudinary/engine.rb +12 -0
  33. data/lib/yarii-cloudinary/version.rb +3 -0
  34. data/lib/yarii-cloudinary.rb +15 -0
  35. metadata +118 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ee27d8a27036bdb708e1a7113769e2ce31ff1cdd7264af66ddb93f9aefd22b86
4
+ data.tar.gz: a3d3c2406eb27d7bd4ceef17be39b550adf2145a2d05fd311343c79c1ffdf672
5
+ SHA512:
6
+ metadata.gz: 87de93d203977671798102933a7fc6f5053c75a9501ac68f1065b1742bde45d0e929562fc8edf9fab81646ee58ce118184a6f06761c48ab9dd4fb2ec27b628b4
7
+ data.tar.gz: bb980195588ace45c272b969cd59f38336f35ed7763183b2e4d83897095b0ec8ee8647e46e787840eb5a5915f4d4e60e6c5d6aa83f292bac2e49eb38c8917c4c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Whitefusion
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Yarii Cloudinary Plugin
2
+
3
+ Short description and motivation. Etc.
4
+
5
+ *Documentation TODO*:
6
+
7
+ * `yarii_editor` upload preset needed in Cloudinary (also media needs to be tagged 'yarii_editor')
8
+ * Add the modal to dashboard extras
9
+ * Add the head renderer (yarii_extra_head)
10
+ * Add the gem initializer
11
+ * Add the route
12
+
13
+ ## Usage
14
+
15
+ How to use my plugin.
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'yarii-cloudinary'
23
+ ```
24
+
25
+ And then execute:
26
+ ```bash
27
+ $ bundle
28
+ ```
29
+
30
+ ## Contributing
31
+ Contribution directions go here.
32
+
33
+ ## License
34
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Yariieditor'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
@@ -0,0 +1,6 @@
1
+ module YariiCloudinary
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ include YariiEditor::ControllerAuthorization
5
+ end
6
+ end
@@ -0,0 +1,33 @@
1
+ module YariiCloudinary
2
+ class MediaController < ApplicationController
3
+ def index
4
+ cloudinary_tag = ENV.fetch('yarii_cloudinary_tag', 'yarii_editor')
5
+ json_images = Cloudinary::Api.resources_by_tag(cloudinary_tag, cloud_name: ENV['yarii_cloudinary_cloud_name'], api_key: ENV['yarii_cloudinary_api_key'], api_secret: ENV['yarii_cloudinary_api_secret'], max_results: 200)['resources']
6
+
7
+ @images = json_images.map do |image|
8
+ {
9
+ path: "v#{image['version']}/#{image['public_id']}",
10
+ id: image['public_id'],
11
+ format: image['format']
12
+ }
13
+ end
14
+
15
+ render layout: false
16
+ end
17
+
18
+ def form_thumbnail
19
+ render partial: 'form_thumbnail', layout: nil, formats: [:html], locals: {public_id: params[:id]}
20
+ end
21
+
22
+ def multiple_form_item
23
+ render_locals = {
24
+ public_id: params[:id],
25
+ name: params[:name],
26
+ index: params[:index],
27
+ input_classes: params[:input_classes],
28
+ placeholder: params[:placeholder]
29
+ }
30
+ render partial: 'multiple_form_item', layout: nil, formats: [:html], locals: render_locals
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ module YariiCloudinary
2
+ module ApplicationHelper
3
+ include ::Webpacker::Helper
4
+
5
+ def current_webpacker_instance
6
+ YariiCloudinary.webpacker
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ import { Controller } from "stimulus"
2
+ //import cloudinary from "cloudinary-core"
3
+
4
+ export default class extends Controller {
5
+ connect() {
6
+ // Not currently used…
7
+ /* this.cl = new cloudinary.Cloudinary({cloud_name: this.data.get("cloud"), secure: true}); */
8
+ console.log("Modal exists")
9
+ }
10
+
11
+ selectMedia(event) {
12
+ this.selectedPublicId = event.currentTarget.dataset.cloudinaryId
13
+ const customEvent = new CustomEvent('selectCloudinaryMedia', { bubbles: true, detail: this })
14
+ this.element.dispatchEvent(customEvent)
15
+ }
16
+
17
+ closeModal() {
18
+ const customEvent = new CustomEvent('closeCloudinaryMedia', { bubbles: true, detail: this })
19
+ this.element.dispatchEvent(customEvent)
20
+ }
21
+ }
@@ -0,0 +1,164 @@
1
+ import { Controller } from "stimulus"
2
+ import axios from "axios"
3
+
4
+ export default class extends Controller {
5
+ static targets = ["rows", "thumbnail", "input"]
6
+
7
+ connect() {
8
+ this.ids = []
9
+ this.currentIndex = -1
10
+ if (this.data.get('ids')) {
11
+ this.ids = this.data.get('ids').split(',')
12
+ }
13
+ this.updateIndex()
14
+
15
+ const uploadPreset = this.data.get('uploadPreset') || 'yarii_editor'
16
+
17
+ this.cloudinaryWidget = cloudinary.createUploadWidget({
18
+ cloudName: this.data.get('cloud'),
19
+ multiple: true,
20
+ sources: [
21
+ 'local',
22
+ 'url'
23
+ ],
24
+ uploadPreset: uploadPreset}, (error, result) => {
25
+ if (!error && result && result.event === "success") {
26
+ this.widgetSuccessCallback(result.info)
27
+ }
28
+ }
29
+ )
30
+ }
31
+
32
+ updateIndex() {
33
+ this.latestIndex = this.ids.length - 1
34
+ }
35
+
36
+ async widgetSuccessCallback(result) {
37
+ const publicId = result.public_id
38
+ if (this.currentIndex == -1) {
39
+ // When adding new images
40
+ this.ids.push(publicId)
41
+ this.updateIndex()
42
+ const formItemPath = this.data.get('formItemPath').replace('/0/', `/${encodeURIComponent(publicId)}/`)
43
+ try {
44
+ const response = await axios.get(formItemPath, {params: {
45
+ name: `${this.data.get('name')}[]`,
46
+ index: this.latestIndex,
47
+ input_classes: this.data.get('inputClasses'),
48
+ placeholder: this.data.get('placeholder')
49
+ }})
50
+ const newRow = document.createElement('template')
51
+ newRow.innerHTML = response.data
52
+ this.rowsTarget.append(newRow.content.cloneNode(true))
53
+ } catch (error) {
54
+ console.log(error)
55
+ }
56
+ }
57
+ else {
58
+ const formItemPath = this.data.get('formItemPath').replace('/0/', `/${encodeURIComponent(publicId)}/`)
59
+ try {
60
+ const response = await axios.get(formItemPath, {params: {
61
+ name: `${this.data.get('name')}[]`,
62
+ index: this.currentIndex,
63
+ input_classes: this.data.get('inputClasses'),
64
+ placeholder: this.data.get('placeholder')
65
+ }})
66
+ const newRow = document.createElement('template')
67
+ newRow.innerHTML = response.data
68
+ this.rowsTarget.replaceChild(newRow.content.cloneNode(true), this.rowsTarget.querySelector(`div[data-index="${this.currentIndex}"]`))
69
+ } catch (error) {
70
+ console.log(error)
71
+ }
72
+ }
73
+ }
74
+
75
+ open() {
76
+ this.currentIndex = parseInt(event.currentTarget.dataset.index, 10)
77
+ this.cloudinaryWidget.open()
78
+ }
79
+
80
+ add() {
81
+ this.currentIndex = -1
82
+ this.cloudinaryWidget.open()
83
+ }
84
+
85
+ remove(event) {
86
+ const indexToRemove = parseInt(event.currentTarget.dataset.index, 10)
87
+ if (confirm('Are you sure you wish to remove this media item?')) {
88
+ this.inputTargets[indexToRemove].value = ""
89
+ this.rowsTarget.querySelector(`div[data-index="${indexToRemove}"]`).classList.add('is-hidden')
90
+ }
91
+ }
92
+
93
+ async addBrowse() {
94
+ this.currentIndex = -1
95
+ const newPath = this.data.get('browsePath')
96
+ this.boundCallbacks = {
97
+ select: this.selectMediaCallback.bind(this),
98
+ close: this.closeMediaCallback.bind(this)
99
+ }
100
+ document.querySelector('#yarii-cloudinary--modal-wrapper').addEventListener('selectCloudinaryMedia', this.boundCallbacks.select)
101
+ document.querySelector('#yarii-cloudinary--modal-wrapper').addEventListener('closeCloudinaryMedia', this.boundCallbacks.close)
102
+
103
+ try {
104
+ const response = await axios.get(newPath)
105
+ document.querySelector('#yarii-cloudinary--modal-wrapper').innerHTML = response.data
106
+ } catch (error) {
107
+ console.log(error)
108
+ }
109
+ }
110
+
111
+ async browse(event) {
112
+ this.currentIndex = parseInt(event.currentTarget.dataset.index, 10)
113
+ const newPath = this.data.get('browsePath')
114
+ this.boundCallbacks = {
115
+ select: this.selectMediaCallback.bind(this),
116
+ close: this.closeMediaCallback.bind(this)
117
+ }
118
+ document.querySelector('#yarii-cloudinary--modal-wrapper').addEventListener('selectCloudinaryMedia', this.boundCallbacks.select)
119
+ document.querySelector('#yarii-cloudinary--modal-wrapper').addEventListener('closeCloudinaryMedia', this.boundCallbacks.close)
120
+
121
+ try {
122
+ const response = await axios.get(newPath)
123
+ document.querySelector('#yarii-cloudinary--modal-wrapper').innerHTML = response.data
124
+ } catch (error) {
125
+ console.log(error)
126
+ }
127
+ }
128
+
129
+ async selectMediaCallback(event) {
130
+ const browseController = event.detail
131
+ const publicId = browseController.selectedPublicId
132
+ if (this.currentIndex == -1) {
133
+ // when adding new images
134
+ this.ids.push(publicId)
135
+ this.updateIndex()
136
+ const formItemPath = this.data.get('formItemPath').replace('/0/', `/${encodeURIComponent(publicId)}/`)
137
+ try {
138
+ const response = await axios.get(formItemPath, {params: {
139
+ name: `${this.data.get('name')}[]`,
140
+ index: this.latestIndex,
141
+ input_classes: this.data.get('inputClasses'),
142
+ placeholder: this.data.get('placeholder')
143
+ }})
144
+ const newRow = document.createElement('template')
145
+ newRow.innerHTML = response.data
146
+ this.rowsTarget.append(newRow.content.cloneNode(true))
147
+ } catch (error) {
148
+ console.log(error)
149
+ }
150
+ } else {
151
+ const thumbnailImage = browseController.element.querySelector(`div[data-cloudinary-id="${publicId}"] figure`).innerHTML
152
+ this.thumbnailTargets[this.currentIndex].innerHTML = `<figure class="image is-128x128 mb-3">${thumbnailImage}</figure>`
153
+ this.inputTargets[this.currentIndex].value = publicId
154
+ }
155
+ browseController.closeModal()
156
+ }
157
+
158
+ closeMediaCallback(event) {
159
+ const browseController = event.detail
160
+ document.querySelector('#yarii-cloudinary--modal-wrapper').removeEventListener('selectCloudinaryMedia', this.boundCallbacks.select)
161
+ document.querySelector('#yarii-cloudinary--modal-wrapper').removeEventListener('closeCloudinaryMedia', this.boundCallbacks.close)
162
+ browseController.element.remove()
163
+ }
164
+ }
@@ -0,0 +1,73 @@
1
+ import { Controller } from "stimulus"
2
+ import axios from "axios"
3
+
4
+ export default class extends Controller {
5
+ static targets = ["thumbnail", "input"]
6
+
7
+ connect() {
8
+ const uploadPreset = this.data.get('uploadPreset') || 'yarii_editor'
9
+
10
+ this.cloudinaryWidget = cloudinary.createUploadWidget({
11
+ cloudName: this.data.get('cloud'),
12
+ multiple: false,
13
+ sources: [
14
+ 'local',
15
+ 'url'
16
+ ],
17
+ uploadPreset: uploadPreset}, (error, result) => {
18
+ if (!error && result && result.event === "success") {
19
+ this.widgetSuccessCallback(result.info)
20
+ }
21
+ }
22
+ )
23
+ }
24
+
25
+ async widgetSuccessCallback(result) {
26
+ const publicId = result.public_id
27
+ this.inputTarget.value = publicId
28
+ const formThumbnailPath = this.data.get('formThumbnailPath').replace('/0/', `/${encodeURIComponent(publicId)}/`)
29
+ try {
30
+ const response = await axios.get(formThumbnailPath)
31
+ this.thumbnailTarget.innerHTML = response.data
32
+ } catch (error) {
33
+ console.log(error)
34
+ }
35
+ }
36
+
37
+ open() {
38
+ this.cloudinaryWidget.open()
39
+ }
40
+
41
+ async browse() {
42
+ const newPath = this.data.get('browsePath')
43
+ this.boundCallbacks = {
44
+ select: this.selectMediaCallback.bind(this),
45
+ close: this.closeMediaCallback.bind(this)
46
+ }
47
+ document.querySelector('#yarii-cloudinary--modal-wrapper').addEventListener('selectCloudinaryMedia', this.boundCallbacks.select)
48
+ document.querySelector('#yarii-cloudinary--modal-wrapper').addEventListener('closeCloudinaryMedia', this.boundCallbacks.close)
49
+
50
+ try {
51
+ const response = await axios.get(newPath)
52
+ document.querySelector('#yarii-cloudinary--modal-wrapper').innerHTML = response.data
53
+ } catch (error) {
54
+ console.log(error)
55
+ }
56
+ }
57
+
58
+ selectMediaCallback(event) {
59
+ const browseController = event.detail
60
+ const publicId = browseController.selectedPublicId
61
+ const thumbnailImage = browseController.element.querySelector(`div[data-cloudinary-id="${publicId}"] figure`).innerHTML
62
+ this.thumbnailTarget.innerHTML = `<figure class="image is-128x128 mb-3">${thumbnailImage}</figure>`
63
+ this.inputTarget.value = publicId
64
+ browseController.closeModal()
65
+ }
66
+
67
+ closeMediaCallback(event) {
68
+ const browseController = event.detail
69
+ document.querySelector('#yarii-cloudinary--modal-wrapper').removeEventListener('selectCloudinaryMedia', this.boundCallbacks.select)
70
+ document.querySelector('#yarii-cloudinary--modal-wrapper').removeEventListener('closeCloudinaryMedia', this.boundCallbacks.close)
71
+ browseController.element.remove()
72
+ }
73
+ }
@@ -0,0 +1,11 @@
1
+ // Load all the controllers within this directory and all subdirectories.
2
+ // Controller files must be named *_controller.js.
3
+
4
+ import { Application } from "stimulus"
5
+ import { definitionsFromContext } from "stimulus/webpack-helpers"
6
+
7
+ const application = Application.start()
8
+ const context = require.context("controllers", true, /_controller\.js$/)
9
+ application.load(definitionsFromContext(context))
10
+
11
+ console.info("cloudinary II:!")
@@ -0,0 +1,2 @@
1
+ import '../../styles/index.scss'
2
+ import "controllers"
@@ -0,0 +1,4 @@
1
+ module YariiCloudinary
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,43 @@
1
+ @charset "utf-8";
2
+
3
+ @mixin thumbnail {
4
+ box-shadow: 0px 2px 5px rgba(0,0,0,0.25);
5
+ border: 1px solid rgba(0,0,0,0.5);
6
+ }
7
+
8
+ .yarii-cloudinary--field {
9
+ @media (min-width: 768px) {
10
+ .level-item {
11
+ padding-right: 10px;
12
+ &:last-of-type {
13
+ padding-right: 0px;
14
+ }
15
+ }
16
+ }
17
+ figure img {
18
+ @include thumbnail;
19
+ }
20
+ .button {
21
+ margin-right: 10px;
22
+ &:last-of-type {
23
+ margin-right: 0;
24
+ }
25
+ }
26
+ }
27
+
28
+ .input.yarii-cloudinary--text-input {
29
+ }
30
+
31
+ .yarii-cloudinary--browse-cell {
32
+ cursor: pointer;
33
+ &:hover {
34
+ background: rgba(0,0,0,0.05);
35
+ }
36
+ figure {
37
+ margin-bottom: 0.5rem;
38
+ img {
39
+ @include thumbnail;
40
+ }
41
+ }
42
+ }
43
+
@@ -0,0 +1,2 @@
1
+ <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
2
+ <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
@@ -0,0 +1,3 @@
1
+ <figure class="image is-128x128 m-auto">
2
+ <%= cl_image_tag public_id, cloud_name: ENV['yarii_cloudinary_cloud_name'], :width => 256, :height => 256, :crop => :thumb, :format => :jpg, :quality => 60 %>
3
+ </figure>
@@ -0,0 +1,3 @@
1
+ <figure class="image is-128x128 mb-3">
2
+ <%= cl_image_tag public_id, cloud_name: ENV['yarii_cloudinary_cloud_name'], :width => 256, :height => 256, :crop => :thumb, :format => :jpg, :quality => 60 %>
3
+ </figure>
@@ -0,0 +1,4 @@
1
+ <!-- Yarii::Cloudinary Media Modal -->
2
+ <script src="https://widget.cloudinary.com/v2.0/global/all.js" type="text/javascript"></script>
3
+ <div id="yarii-cloudinary--modal-wrapper">
4
+ </div>
@@ -0,0 +1,25 @@
1
+ <div data-index="<%= index %>" class="level">
2
+ <div class="level-item is-narrow">
3
+ <div data-target="cloudinary-multiple-media.thumbnail">
4
+ <% if public_id.present? %>
5
+ <%= render 'yarii_cloudinary/media/form_thumbnail', public_id: public_id %>
6
+ <% end %>
7
+ </div>
8
+ </div>
9
+ <div class="level-item">
10
+ <%= content_tag :input, nil, name: name, value: public_id, class: input_classes, type: 'text', placeholder: placeholder, data: {target: 'cloudinary-multiple-media.input'} %>
11
+ </div>
12
+ <div class="level-item is-narrow">
13
+ <button data-index="<%= index %>" data-action="cloudinary-multiple-media#open" class="button is-primary">
14
+ <span class="icon"><i class="fa fa-upload"></i></span>
15
+ <span>Upload</span>
16
+ </button>
17
+ <button data-index="<%= index %>" data-action="cloudinary-multiple-media#browse" class="button is-success">
18
+ <span class="icon"><i class="fa fa-picture-o"></i></span>
19
+ <span>Browse</span>
20
+ </button>
21
+ <button data-index="<%= index %>" data-action="cloudinary-multiple-media#remove" class="button is-danger">
22
+ <i class="fa fa-trash"></i>
23
+ </button>
24
+ </div>
25
+ </div>
@@ -0,0 +1,22 @@
1
+ <div data-controller="cloudinary-browse-media" id="yarii-cloudinary--modal" class="modal is-active">
2
+ <div class="modal-background"></div>
3
+ <div class="modal-card">
4
+ <header class="modal-card-head">
5
+ <p class="modal-card-title">Browse Cloudinary</p>
6
+ <button data-action="cloudinary-browse-media#closeModal" class="delete" aria-label="close"></button>
7
+ </header>
8
+ <section class="modal-card-body">
9
+ <div class="columns is-multiline is-mobile">
10
+ <% @images.each do |image| %>
11
+ <div data-action="click->cloudinary-browse-media#selectMedia" data-cloudinary-id="<%= image[:id] %>" role="button" class="yarii-cloudinary--browse-cell column is-one-third-tablet is-one-third-desktop is-half-mobile has-text-centered">
12
+ <%= render 'browse_thumbnail', public_id: image[:path] %>
13
+ <div class="image-name"><strong><%= image[:id] %></strong>.<%= image[:format] %></div>
14
+ </div>
15
+ <% end %>
16
+ </div>
17
+ </section>
18
+ <footer class="modal-card-foot">
19
+ <button data-action="cloudinary-browse-media#closeModal" class="button is-success">Done</button>
20
+ </footer>
21
+ </div>
22
+ </div>
@@ -0,0 +1,42 @@
1
+ <%-
2
+ input_classes = ['input yarii-cloudinary--text-input']
3
+ input_classes << className if local_assigns[:className]
4
+ name = name_from_variable(assigns)
5
+ value = value_from_variable(assigns)
6
+ %>
7
+ <div
8
+ data-controller="cloudinary-single-media"
9
+ data-cloudinary-single-media-cloud="<%= ENV['yarii_cloudinary_cloud_name'] %>"
10
+ <% if ENV['yarii_cloudinary_tag'] -%>data-cloudinary-single-media-upload-preset="<%= ENV['yarii_cloudinary_tag'] %>"<% end -%>
11
+ data-cloudinary-single-media-browse-path="<%= yarii_cloudinary.media_path %>"
12
+ data-cloudinary-single-media-form-thumbnail-path="<%= yarii_cloudinary.form_thumbnail_medium_path(0) %>"
13
+ class="yarii-cloudinary--field field"
14
+ >
15
+ <label class="label"><%= label %></label>
16
+ <div class="control">
17
+ <div class="level">
18
+ <div class="level-item is-narrow">
19
+ <div data-target="cloudinary-single-media.thumbnail">
20
+ <% if value.present? %>
21
+ <%= render 'yarii_cloudinary/media/form_thumbnail', public_id: value %>
22
+ <% else %>
23
+ <span class="icon is-medium has-text-info"><i class="fa fa-picture-o fa-lg"></i></span>
24
+ <% end %>
25
+ </div>
26
+ </div>
27
+ <div class="level-item">
28
+ <%= content_tag :input, nil, name: name, value: value, class: input_classes.join(' '), type: 'text', placeholder: placeholder, data: {target: 'cloudinary-single-media.input'} %>
29
+ </div>
30
+ <div class="level-item is-narrow">
31
+ <button data-action="cloudinary-single-media#open" class="button is-primary">
32
+ <span class="icon"><i class="fa fa-upload"></i></span>
33
+ <span>Upload</span>
34
+ </button>
35
+ <button data-action="cloudinary-single-media#browse" class="button is-success">
36
+ <span class="icon"><i class="fa fa-picture-o"></i></span>
37
+ <span>Browse</span>
38
+ </button>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </div>
@@ -0,0 +1,50 @@
1
+ <%-
2
+ input_classes = ['input yarii-cloudinary--text-input']
3
+ input_classes << className if local_assigns[:className]
4
+ name = name_from_variable(local_assigns)
5
+ value = value_from_variable(local_assigns)
6
+ %>
7
+ <div
8
+ data-controller="cloudinary-multiple-media"
9
+ <% if value.is_a?(Array)
10
+ -%>data-cloudinary-multiple-media-ids="<%= value.join(',') %>"
11
+ <% end
12
+ -%>
13
+ data-cloudinary-multiple-media-cloud="<%= ENV['yarii_cloudinary_cloud_name'] %>"
14
+ <% if ENV['yarii_cloudinary_tag'] -%>data-cloudinary-multiple-media-upload-preset="<%= ENV['yarii_cloudinary_tag'] %>"<% end -%>
15
+ data-cloudinary-multiple-media-browse-path="<%= yarii_cloudinary.media_path %>"
16
+ data-cloudinary-multiple-media-form-item-path="<%= yarii_cloudinary.multiple_form_item_medium_path(0) %>"
17
+ data-cloudinary-multiple-media-name="<%= name %>"
18
+ data-cloudinary-multiple-media-input-classes="<%= input_classes.join(' ') %>"
19
+ data-cloudinary-multiple-media-placeholder="<%= placeholder.gsub(/"/, '&quot;') %>"
20
+ class="yarii-cloudinary--field field"
21
+ >
22
+ <label class="label"><%= label %></label>
23
+ <div class="control">
24
+ <div data-target="cloudinary-multiple-media.rows">
25
+ <% if value.is_a? Array %>
26
+ <% value.each_with_index do |public_id, index| %>
27
+ <%=
28
+ render 'yarii_cloudinary/media/multiple_form_item',
29
+ name: "#{name}[]",
30
+ public_id: public_id,
31
+ index: index,
32
+ input_classes: input_classes.join(' '),
33
+ placeholder: placeholder
34
+ %>
35
+ <% end %>
36
+ <% end %>
37
+ </div>
38
+
39
+ <div class="has-text-centered mt-6">
40
+ <button data-action="cloudinary-multiple-media#add" class="button is-primary">
41
+ <span class="icon"><i class="fa fa-upload"></i></span>
42
+ <span>Add via Upload</span>
43
+ </button>
44
+ <button data-action="cloudinary-multiple-media#addBrowse" class="button is-success">
45
+ <span class="icon"><i class="fa fa-picture-o"></i></span>
46
+ <span>Add via Browse</span>
47
+ </button>
48
+ </div>
49
+ </div>
50
+ </div>
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ YariiCloudinary::Engine.routes.draw do
2
+ resources :media do
3
+ member do
4
+ get 'form_thumbnail'
5
+ get 'multiple_form_item'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2
+
3
+ const environment = require('./environment')
4
+
5
+ module.exports = environment.toWebpackConfig()
@@ -0,0 +1,3 @@
1
+ const { environment } = require('@rails/webpacker')
2
+
3
+ module.exports = environment
@@ -0,0 +1,5 @@
1
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production'
2
+
3
+ const environment = require('./environment')
4
+
5
+ module.exports = environment.toWebpackConfig()
@@ -0,0 +1,5 @@
1
+ process.env.NODE_ENV = process.env.NODE_ENV || 'staging'
2
+
3
+ const environment = require('./environment')
4
+
5
+ module.exports = environment.toWebpackConfig()
@@ -0,0 +1,5 @@
1
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2
+
3
+ const environment = require('./environment')
4
+
5
+ module.exports = environment.toWebpackConfig()
@@ -0,0 +1,110 @@
1
+ # Note: You must restart bin/webpack-dev-server for changes to take effect
2
+
3
+ default: &default
4
+ source_path: app/javascript
5
+ source_entry_path: packs
6
+ public_root_path: public
7
+ # use a different sub-folder name
8
+ public_output_path: yarii-cloudinary-packs
9
+
10
+ cache_path: tmp/cache/webpacker
11
+ check_yarn_integrity: false
12
+ webpack_compile_output: false
13
+
14
+ # Additional paths webpack should lookup modules
15
+ # ['app/assets', 'engine/foo/app/assets']
16
+ resolved_paths: []
17
+
18
+ # Reload manifest.json on all requests so we reload latest compiled packs
19
+ cache_manifest: false
20
+
21
+ # Extract and emit a css file
22
+ extract_css: true
23
+
24
+ static_assets_extensions:
25
+ - .jpg
26
+ - .jpeg
27
+ - .png
28
+ - .gif
29
+ - .tiff
30
+ - .ico
31
+ - .svg
32
+ - .eot
33
+ - .otf
34
+ - .ttf
35
+ - .woff
36
+ - .woff2
37
+
38
+ extensions:
39
+ - .mjs
40
+ - .js
41
+ - .sass
42
+ - .scss
43
+ - .css
44
+ - .module.sass
45
+ - .module.scss
46
+ - .module.css
47
+ - .png
48
+ - .svg
49
+ - .gif
50
+ - .jpeg
51
+ - .jpg
52
+
53
+ development:
54
+ <<: *default
55
+ compile: true
56
+
57
+ # Verifies that versions and hashed value of the package contents in the project's package.json
58
+ check_yarn_integrity: true
59
+
60
+ # Reference: https://webpack.js.org/configuration/dev-server/
61
+ dev_server:
62
+ https: false
63
+ host: localhost
64
+ port: 3035
65
+ public: localhost:3035
66
+ hmr: false
67
+ # Inline should be set to true if using HMR
68
+ inline: true
69
+ overlay: true
70
+ compress: true
71
+ disable_host_check: true
72
+ use_local_ip: false
73
+ quiet: false
74
+ headers:
75
+ 'Access-Control-Allow-Origin': '*'
76
+ watch_options:
77
+ ignored: '**/node_modules/**'
78
+
79
+
80
+ test:
81
+ <<: *default
82
+ compile: true
83
+
84
+ # Compile test packs to a separate directory
85
+ public_output_path: packs-test
86
+
87
+ staging:
88
+ <<: *default
89
+
90
+ # Staging, like Production, depends on precompilation of packs prior to booting for performance.
91
+ compile: false
92
+
93
+ # Extract and emit a css file
94
+ extract_css: true
95
+
96
+ # Cache manifest.json for performance
97
+ cache_manifest: true
98
+
99
+
100
+ production:
101
+ <<: *default
102
+
103
+ # Production depends on precompilation of packs prior to booting for performance.
104
+ compile: false
105
+
106
+ # Extract and emit a css file
107
+ extract_css: true
108
+
109
+ # Cache manifest.json for performance
110
+ cache_manifest: true
@@ -0,0 +1,12 @@
1
+ class CreateYariiSites < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :yarii_sites do |t|
4
+ t.string :title
5
+ t.string :preview_base_url
6
+ t.string :published_base_url
7
+ t.string :content_base_path
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ def ensure_log_goes_to_stdout
2
+ old_logger = Webpacker.logger
3
+ Webpacker.logger = ActiveSupport::Logger.new(STDOUT)
4
+ yield
5
+ ensure
6
+ Webpacker.logger = old_logger
7
+ end
8
+
9
+
10
+ namespace :yarii_cloudinary do
11
+ namespace :webpacker do
12
+ desc "Install deps with yarn"
13
+ task :yarn_install do
14
+ Dir.chdir(File.join(__dir__, "../..")) do
15
+ system "yarn install --no-progress --production"
16
+ end
17
+ end
18
+
19
+ desc "Compile JavaScript packs using webpack for production with digests"
20
+ task compile: [:yarn_install, :environment] do
21
+ Webpacker.with_node_env("production") do
22
+ ensure_log_goes_to_stdout do
23
+ if YariiCloudinary.webpacker.commands.compile
24
+ # Successful compilation!
25
+ puts "YariiCloudinary Plugin -- Webpacker success"
26
+ else
27
+ # Failed compilation
28
+ puts "YariiCloudinary Plugin -- something's wrong with Webpacker!"
29
+ exit!
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def yarn_install_available?
38
+ rails_major = Rails::VERSION::MAJOR
39
+ rails_minor = Rails::VERSION::MINOR
40
+
41
+ rails_major > 5 || (rails_major == 5 && rails_minor >= 1)
42
+ end
43
+
44
+ def enhance_assets_precompile
45
+ # yarn:install was added in Rails 5.1
46
+ deps = yarn_install_available? ? [] : ["yarii_cloudinary:webpacker:yarn_install"]
47
+ Rake::Task["assets:precompile"].enhance(deps) do
48
+ Rake::Task["yarii_cloudinary:webpacker:compile"].invoke
49
+ end
50
+ end
51
+
52
+ # Compile packs after we've compiled all other assets during precompilation
53
+ skip_webpacker_precompile = %w(no false n f).include?(ENV["WEBPACKER_PRECOMPILE"])
54
+
55
+ unless skip_webpacker_precompile
56
+ if Rake::Task.task_defined?("assets:precompile")
57
+ enhance_assets_precompile
58
+ else
59
+ Rake::Task.define_task("assets:precompile" => "yarii_cloudinary:webpacker:compile")
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ module YariiCloudinary
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace YariiCloudinary
4
+
5
+ ROOT_PATH = Pathname.new(File.join(__dir__, "..", ".."))
6
+
7
+ config.app_middleware.use(
8
+ Rack::Static,
9
+ urls: ["/yarii-cloudinary-packs"], root: ROOT_PATH.join("public")
10
+ )
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module YariiCloudinary
2
+ VERSION = '0.2.0'
3
+ end
@@ -0,0 +1,15 @@
1
+ require "yarii-cloudinary/engine"
2
+
3
+ module YariiCloudinary
4
+ ROOT_PATH = Pathname.new(File.join(__dir__, ".."))
5
+
6
+ class << self
7
+ def webpacker
8
+ @webpacker ||= ::Webpacker::Instance.new(
9
+ root_path: ROOT_PATH,
10
+ config_path: ROOT_PATH.join("config/webpacker.yml")
11
+ )
12
+ end
13
+ end
14
+ end
15
+
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yarii-cloudinary
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Jared White
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: webpacker
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: cloudinary
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.12'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ description: Allows images to be loaded and viewed in Yarii via the Cloudinary service
56
+ email:
57
+ - jared@jaredwhite.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - app/controllers/yarii_cloudinary/application_controller.rb
66
+ - app/controllers/yarii_cloudinary/media_controller.rb
67
+ - app/helpers/yarii_cloudinary/application_helper.rb
68
+ - app/javascript/controllers/cloudinary_browse_media_controller.js
69
+ - app/javascript/controllers/cloudinary_multiple_media_controller.js
70
+ - app/javascript/controllers/cloudinary_single_media_controller.js
71
+ - app/javascript/controllers/index.js
72
+ - app/javascript/packs/application.js
73
+ - app/jobs/yarii_cloudinary/application_job.rb
74
+ - app/styles/index.scss
75
+ - app/views/yarii_cloudinary/application/yarii_cloudinary_head.erb
76
+ - app/views/yarii_cloudinary/media/_browse_thumbnail.html.erb
77
+ - app/views/yarii_cloudinary/media/_form_thumbnail.html.erb
78
+ - app/views/yarii_cloudinary/media/_modal.html.erb
79
+ - app/views/yarii_cloudinary/media/_multiple_form_item.html.erb
80
+ - app/views/yarii_cloudinary/media/index.html.erb
81
+ - app/views/yarii_editor/editor/_cloudinary.html.erb
82
+ - app/views/yarii_editor/editor/_cloudinary_multiple.html.erb
83
+ - config/routes.rb
84
+ - config/webpack/development.js
85
+ - config/webpack/environment.js
86
+ - config/webpack/production.js
87
+ - config/webpack/staging.js
88
+ - config/webpack/test.js
89
+ - config/webpacker.yml
90
+ - db/migrate/20190923000809_create_yarii_sites.rb
91
+ - lib/tasks/yarii_cloudinary_tasks.rake
92
+ - lib/yarii-cloudinary.rb
93
+ - lib/yarii-cloudinary/engine.rb
94
+ - lib/yarii-cloudinary/version.rb
95
+ homepage: https://whitefusion.io
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubygems_version: 3.0.8
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Allows images to be loaded and viewed in Yarii via the Cloudinary service
118
+ test_files: []