yarii-cloudinary 0.2.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 +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: []
|