yarii-cloudinary 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +34 -0
- data/Rakefile +32 -0
- data/app/controllers/yarii_cloudinary/application_controller.rb +6 -0
- data/app/controllers/yarii_cloudinary/media_controller.rb +33 -0
- data/app/helpers/yarii_cloudinary/application_helper.rb +9 -0
- data/app/javascript/controllers/cloudinary_browse_media_controller.js +21 -0
- data/app/javascript/controllers/cloudinary_multiple_media_controller.js +164 -0
- data/app/javascript/controllers/cloudinary_single_media_controller.js +73 -0
- data/app/javascript/controllers/index.js +11 -0
- data/app/javascript/packs/application.js +2 -0
- data/app/jobs/yarii_cloudinary/application_job.rb +4 -0
- data/app/styles/index.scss +43 -0
- data/app/views/yarii_cloudinary/application/yarii_cloudinary_head.erb +2 -0
- data/app/views/yarii_cloudinary/media/_browse_thumbnail.html.erb +3 -0
- data/app/views/yarii_cloudinary/media/_form_thumbnail.html.erb +3 -0
- data/app/views/yarii_cloudinary/media/_modal.html.erb +4 -0
- data/app/views/yarii_cloudinary/media/_multiple_form_item.html.erb +25 -0
- data/app/views/yarii_cloudinary/media/index.html.erb +22 -0
- data/app/views/yarii_editor/editor/_cloudinary.html.erb +42 -0
- data/app/views/yarii_editor/editor/_cloudinary_multiple.html.erb +50 -0
- data/config/routes.rb +8 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/staging.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +110 -0
- data/db/migrate/20190923000809_create_yarii_sites.rb +12 -0
- data/lib/tasks/yarii_cloudinary_tasks.rake +61 -0
- data/lib/yarii-cloudinary/engine.rb +12 -0
- data/lib/yarii-cloudinary/version.rb +3 -0
- data/lib/yarii-cloudinary.rb +15 -0
- 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,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,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,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,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(/"/, '"') %>"
|
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,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,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,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: []
|