refinerycms-dragonfly-delayed 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f33bc442ac85fa16a574513dc31b61187475104
4
+ data.tar.gz: 3adec407f96233d2dbfaa5492df44f4bd655c236
5
+ SHA512:
6
+ metadata.gz: 80ed449e7d5c69ab7eeb02de954e7b4d5b8acf3f6e0b6f491acafc4836696cf6b70f42b1795b0d8f6739c587f37745152fb03771ce5738bcf22cfe1d1f294a7d
7
+ data.tar.gz: 7ab1cae00f96960e0c621f058d32e744768905e8ce7666d993434bfa31b7d1b1023da7dc061c5b15ffe1c390abd8d7b298de6bda48c7c81400000241c0f2d422
@@ -0,0 +1,36 @@
1
+ # Refinery CMS Dragonfly Delayed
2
+
3
+ Generate Images Thumbnails in background processing jobs
4
+
5
+ ## Requirements
6
+
7
+ Refinery CMS 2.x
8
+
9
+ ## Install
10
+
11
+ Open up your ``Gemfile`` and at the bottom, add this line:
12
+
13
+ ```ruby
14
+ gem 'refinerycms-dragonfly-delayed', github: 'Captive-Studio/refinerycms-dragonfly-delayed'
15
+ ```
16
+
17
+ Now, run ``bundle install``
18
+
19
+ Next, to install the blog plugin run:
20
+
21
+ rails generate refinery:dragonfly_delayed
22
+
23
+ Run database migrations:
24
+
25
+ rake db:migrate
26
+
27
+ ## Running Jobs
28
+
29
+ * In your Procfile, add the following line to configure the worker process :
30
+
31
+ ```
32
+ worker: rake jobs:work
33
+ ```
34
+
35
+ * Configure a worker process on your hosting environment
36
+
@@ -0,0 +1,221 @@
1
+ /*
2
+ * Function: WYMeditor.loadCss
3
+ * Loads a stylesheet in the document.
4
+ *
5
+ * Parameters:
6
+ * href - The CSS path.
7
+ */
8
+ WYMeditor.loadCss = function(href) {
9
+ $("<link rel='stylesheet' />").attr('href', href).appendTo($('head').get(0));
10
+ };
11
+
12
+ /********** DIALOGS **********/
13
+
14
+ WYMeditor.INIT_DIALOG = function(wym, selected, isIframe) {
15
+
16
+ var selected = selected || wym.selected();
17
+ var dialog = $("#"+wym._options.dialogId);
18
+ var doc = $(dialog.find('iframe').contents());
19
+ var dialogType = dialog.find('#wym_dialog_type').val();
20
+ if (wym._selected_image) {
21
+ var replaceable = $(wym._selected_image);
22
+ } else {
23
+ var replaceable = $(wym._doc.body).find('#' + wym._current_unique_stamp);
24
+ }
25
+
26
+ // focus first textarea or input type text element
27
+ dialog.find('input[type=text], textarea').first().focus();
28
+
29
+ // init close_dialog when user clicks on cancel button
30
+ doc.find('body').addClass('wym_iframe_body').find('#cancel_button').add(dialog.find('.close_dialog')).click(function(e){
31
+ wym.close_dialog(e, true);
32
+ });
33
+
34
+ // init close_dialog when user clicks on small x icon at the top of dialog
35
+ $('.ui-dialog-titlebar .ui-dialog-titlebar-close').click(function(e){
36
+ wym.close_dialog(e, true);
37
+ });
38
+
39
+ //pre-init functions
40
+ if($.isFunction(wym._options.preInitDialog)) {
41
+ wym._options.preInitDialog(wym, window);
42
+ }
43
+
44
+ $(wym._options.dialogLinkSelector).find(wym._options.submitSelector).click(function(e)
45
+ {
46
+ if ((sUrl = $(wym._options.hrefSelector).val()).length > 0)
47
+ {
48
+ if (replaceable.get(0) != null) {
49
+ var link = $('<a></a>').attr({href:sUrl, title: $(wym._options.titleSelector).val()})
50
+ if ((target = $(wym._options.targetSelector).val()) != null && target.length > 0) {
51
+ link.attr('target', target);
52
+ }
53
+
54
+ // now grab what was selected in the editor and chuck it inside the link.
55
+ if (!wym._selected_image)
56
+ {
57
+ // ensure some attributes are copied across to the new link.
58
+ link.attr({'style': replaceable.attr('style'), 'class': replaceable.attr('class')});
59
+
60
+ link.html(replaceable.html());
61
+ replaceable.replaceWith($('<div/>').append(link).html());
62
+ }
63
+ else
64
+ {
65
+ if ((parent = replaceable.parent().get(0)) != null && parent.tagName.toUpperCase() == "A") {
66
+ $(parent).attr({href: link.attr('href'), title: $(wym._options.titleSelector).val(), target: target});
67
+ }
68
+ else {
69
+ replaceable.before(link);
70
+ $(link).append(replaceable.get(0));
71
+ }
72
+ }
73
+ }
74
+ else {
75
+ wym._exec(WYMeditor.CREATE_LINK, wym._current_unique_stamp);
76
+
77
+ $("a[href=" + wym._current_unique_stamp + "]", wym._doc.body)
78
+ .attr(WYMeditor.HREF, sUrl)
79
+ .attr(WYMeditor.TITLE, $(wym._options.titleSelector).val())
80
+ .attr(WYMeditor.TARGET, $(wym._options.targetSelector).val());
81
+ }
82
+ }
83
+ // fire a click event on the dialogs close button
84
+ wym.close_dialog(e);
85
+ });
86
+
87
+ //auto populate image fields if selected image
88
+ if(wym._selected_image) {
89
+ imgDialog = $(wym._options.dialogImageSelector);
90
+ img = $(wym._selected_image);
91
+ size = (
92
+ (img.attr(WYMeditor.REL)
93
+ || doc.find('#existing_image_size_area li.selected a').attr(WYMeditor.REL)
94
+ || doc.find('#existing_image_size_area li.selected a').attr('rel')) || ""
95
+ );
96
+ src = img.attr(WYMeditor.SRC);
97
+ if (size.length > 0) {
98
+ src = src.replace('_' + size + '.', '.');
99
+ doc.find('#existing_image_size_area li.selected').removeClass('selected');
100
+ doc.find("#existing_image_size_area li a[href='#" + size + "']").parents('li:first').addClass('selected');
101
+ }
102
+
103
+ imgDialog.find(wym._options.srcSelector).val(src);
104
+ imgDialog.find(wym._options.titleSelector).val(img.attr(WYMeditor.TITLE));
105
+ imgDialog.find(wym._options.altSelector).val(img.attr(WYMeditor.ALT));
106
+ imgDialog.find(wym._options.sizeSelector).val(size);
107
+
108
+ (src = src.split('.')).pop();
109
+ doc.find("#existing_image_area_content li img[src^='" + src + "']").parents('li:first').addClass('selected');
110
+ }
111
+
112
+ $(wym._options.dialogImageSelector).find(wym._options.submitSelector).click(function(e) {
113
+ form = $(this.form);
114
+ if ((url = form.find(wym._options.srcSelector).val()) != null && url.length > 0) {
115
+ (image = $(wym._doc.createElement("IMG")))
116
+ .attr(WYMeditor.SRC, url)
117
+ .attr(WYMeditor.TITLE, form.find(wym._options.titleSelector).val())
118
+ .attr(WYMeditor.ALT, form.find(wym._options.altSelector).val())
119
+ .attr(WYMeditor.REL, form.find(wym._options.sizeSelector).val())
120
+
121
+ $.getJSON('/dragonfly_delayed/' + url.split('/')[3], function(data) {
122
+ image.attr('width', data['width'])
123
+ .attr('heigth', data['height']);
124
+ });
125
+
126
+ // ensure we know where to put the image.
127
+ if (replaceable == null) {
128
+ replaceable = $(wym._doc.body).find("#" + wym._current_unique_stamp);
129
+ }
130
+ if (replaceable != null) {
131
+ replaceable.after(image).remove();
132
+ }
133
+
134
+ // fire a click event on the dialogs close button
135
+ wym.close_dialog(e);
136
+ } else {
137
+ // remove any save loader animations.
138
+ $('iframe').contents().find('.save-loader').remove();
139
+ // tell the user.
140
+ alert("Please select an image to insert.");
141
+ }
142
+ e.preventDefault();
143
+ });
144
+
145
+ $(wym._options.dialogTableSelector).find(wym._options.submitSelector).click(function(e) {
146
+ if((iRows = $(wym._options.rowsSelector).val()) > 0 && (iCols = $(wym._options.colsSelector).val()) > 0)
147
+ {
148
+ //create the table and the caption
149
+ (table = wym._doc.createElement(WYMeditor.TABLE)).createCaption().innerHTML = $(wym._options.captionSelector).val();
150
+
151
+ //create the rows and cells
152
+ for(x=0; x<iRows; x++) {
153
+ newRow = table.insertRow(x);
154
+ for(y=0; y<iCols; y++) {
155
+ newRow.insertCell(y);
156
+ }
157
+ }
158
+
159
+ //append the table after the selected container
160
+ var node = $(wym.findUp(wym.container(), WYMeditor.MAIN_CONTAINERS)).get(0);
161
+ if(!node || !node.parentNode) $(wym._doc.body).append(table);
162
+ else $(node).after(table);
163
+ }
164
+ // fire a click event on the dialogs close button
165
+ wym.close_dialog(e);
166
+ });
167
+
168
+ $(wym._options.dialogPasteSelector).find(wym._options.submitSelector).click(function(e) {
169
+ wym.paste($(wym._options.textSelector).val());
170
+
171
+ wym.close_dialog(e);
172
+ });
173
+
174
+ $(wym._options.dialogPreviewSelector).find(wym._options.previewSelector).html(wym.xhtml());
175
+
176
+ //post-init functions
177
+ if($.isFunction(wym._options.postInitDialog)) {
178
+ wym._options.postInitDialog(wym,window);
179
+ }
180
+ };
181
+
182
+ WYMeditor.editor.prototype.close_dialog = function(e, cancelled) {
183
+ if (cancelled)
184
+ {
185
+ // if replaceable exists, replace it with its own html contents.
186
+ if ((span = $(this._doc.body).find('span#' + this._current_unique_stamp)).length > 0) {
187
+ span.parent().html(span.parent().html().replace(new RegExp(["<span(.+?)", span.attr('id'), "(.+?)<\/span>"].join("")), span.html()));
188
+ }
189
+ // https://github.com/refinery/refinerycms/issues/888
190
+ if (node = $(this._doc.body).find('#' + this._current_unique_stamp)) {
191
+ node.attr("id", (node.attr('_id_before_replaceable') || ""));
192
+ node.removeAttr("_id_before_replaceable");
193
+ }
194
+
195
+ if (this._undo_on_cancel == true) {
196
+ this._exec("undo");
197
+ }
198
+ else if (this._redo_on_cancel == true) {
199
+ this._exec("redo");
200
+ }
201
+ }
202
+
203
+ if ($.browser.msie && parseInt($.browser.version) < 8)
204
+ {
205
+ this._iframe.contentWindow.focus();
206
+ }
207
+
208
+ $("#" + wym._options.dialogId).dialog("close").remove();
209
+
210
+ // ensure links can't be navigated to.
211
+ $(this._doc).find('a[href]').click(function(e){e.preventDefault();});
212
+
213
+ if (e) {
214
+ e.preventDefault();
215
+ }
216
+ };
217
+
218
+ // from http://simonwillison.net/2006/Jan/20/escape/#p-6
219
+ RegExp.escape = function(text) {
220
+ return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
221
+ };
@@ -0,0 +1,17 @@
1
+ module Refinery
2
+ module DragonflyDelayed
3
+ class ThumbnailGeometriesController < ::ApplicationController
4
+ def show
5
+ app = ::Dragonfly[:refinery_images]
6
+ job = Dragonfly::Job.deserialize params[:id], app
7
+ fetch = job.steps.select {|job| job.is_a? Dragonfly::Job::Fetch}.first
8
+ thumb = job.steps.select {|job| job.is_a? Dragonfly::Job::Process and job.name == :thumb}.first
9
+ original_image = Refinery::Image.where(image_uid: fetch.uid).first
10
+
11
+ geometry = thumb.arguments.first
12
+ thumbnail_dimensions = original_image.thumbnail_dimensions geometry
13
+ render json: {width: thumbnail_dimensions[:width], height: thumbnail_dimensions[:height]}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module Refinery
2
+ module DragonflyDelayed
3
+
4
+ class ImageResizer
5
+ class << self
6
+ def resize_images_in_queue
7
+ dragonfly_app = ::Dragonfly[:refinery_images]
8
+ Thumb.where(generated: false).find_each do |thumb|
9
+ job = Dragonfly::Job.deserialize thumb.signature, dragonfly_app
10
+ uid = job.store
11
+ thumb.update_attributes uid: uid, generated: true
12
+ end
13
+ end
14
+
15
+ def register_job_to_process job
16
+ thumb = Thumb.where(signature: job.serialize).first_or_initialize
17
+ if thumb.new_record?
18
+ thumb.save
19
+ thumb.delay.store!
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module Refinery
2
+ module DragonflyDelayed
3
+
4
+ class Thumb < ActiveRecord::Base
5
+ self.table_name = 'thumbs'
6
+
7
+ attr_accessible :generated, :signature, :uid
8
+
9
+ validates :signature, presence: true, uniqueness: true
10
+ validates :uid, uniqueness: {allow_nil: true}
11
+
12
+ def store!
13
+ dragonfly_app = ::Dragonfly[:refinery_images]
14
+ job = Dragonfly::Job.deserialize signature, dragonfly_app
15
+ uid = job.store
16
+ update_attributes uid: uid, generated: true
17
+ p "[#{Time.now}] Resized #{uid}"
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ Refinery::Core::Engine.routes.append do
2
+
3
+ namespace :dragonfly_delayed do
4
+ resources :thumbnail_geometries, path: '', only: :show
5
+ end
6
+
7
+ end
@@ -0,0 +1,11 @@
1
+ class CreateThumbs < ActiveRecord::Migration
2
+ def change
3
+ create_table :thumbs do |t|
4
+ t.string :signature
5
+ t.string :uid
6
+ t.boolean :generated, default: false
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ class CreateDelayedJobs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :delayed_jobs, force: true do |table|
4
+ table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
5
+ table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
6
+ table.text :handler, null: false # YAML-encoded string of the object that will do work
7
+ table.text :last_error # reason for last failure (See Note below)
8
+ table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
9
+ table.datetime :locked_at # Set when a client is working on this object
10
+ table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
11
+ table.string :locked_by # Who is working on this object (if locked)
12
+ table.string :queue # The name of the queue this job is in
13
+ table.timestamps null: true
14
+ end
15
+
16
+ add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
17
+ end
18
+
19
+ def self.down
20
+ drop_table :delayed_jobs
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module Refinery
2
+ class DragonflyDelayedGenerator < Rails::Generators::Base
3
+
4
+ def rake_db
5
+ rake "refinery_dragonfly_delayed:install:migrations"
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ # require 'refinerycms-dragonfly-delayed/image_resizer'
2
+ # require 'refinerycms-dragonfly-delayed/thumb'
3
+ require 'dragonfly'
4
+ #
5
+
6
+ require 'delayed_job_active_record'
7
+ require 'refinerycms-core'
8
+
9
+ module Refinery
10
+
11
+ module DragonflyDelayed
12
+ require 'refinery/dragonfly_delayed/engine'
13
+
14
+ ::Dragonfly[:refinery_images].configure do |config|
15
+ config.server.before_serve do |job, env|
16
+ already_generated_thumb = Thumb.where(signature: job.serialize, generated: true).first
17
+ location = if already_generated_thumb.present?
18
+ ::Dragonfly[:refinery_images].datastore.url_for(already_generated_thumb.uid)
19
+ else
20
+ fetch = job.steps.select {|job| job.is_a? Dragonfly::Job::Fetch}.first
21
+ original_image = Refinery::Image.where(image_uid: fetch.uid).first
22
+ throw :halt, [ 404, {}, [] ] if original_image.blank?
23
+
24
+ ImageResizer.register_job_to_process job
25
+ original_image.image.remote_url
26
+ end
27
+ throw :halt, [ 302, {'Location' => location}, [] ]
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,10 @@
1
+ module Refinery
2
+ module DragonflyDelayed
3
+ class Engine < Rails::Engine
4
+ extend Refinery::Engine
5
+ isolate_namespace Refinery::DragonflyDelayed
6
+
7
+ engine_name :refinery_dragonfly_delayed
8
+ end
9
+ end
10
+ end
@@ -0,0 +1 @@
1
+ require 'refinery/dragonfly_delayed'
@@ -0,0 +1,13 @@
1
+ namespace :refinery do
2
+
3
+ namespace :dragonfly_delayed do
4
+
5
+ # call this task by running: rake refinery:dragonfly_delayed:my_task
6
+ # desc "Description of my task below"
7
+ # task :my_task => :environment do
8
+ # # add your logic here
9
+ # end
10
+
11
+ end
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: refinerycms-dragonfly-delayed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Captive Studio Dev Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.19
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.19
27
+ - !ruby/object:Gem::Dependency
28
+ name: dragonfly
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.14
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.14
41
+ - !ruby/object:Gem::Dependency
42
+ name: delayed_job_active_record
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: refinerycms-testing
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.1.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.1.0
97
+ description:
98
+ email: ninja@captive.fr
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - Readme.md
104
+ - app/assets/javascripts/wymeditor/functions.js.erb
105
+ - app/controllers/refinery/dragonfly_delayed/thumbnail_geometries_controller.rb
106
+ - app/models/refinery/dragonfly_delayed/image_resizer.rb
107
+ - app/models/refinery/dragonfly_delayed/thumb.rb
108
+ - config/routes.rb
109
+ - db/migrate/1_create_thumbs.rb
110
+ - db/migrate/2_create_delayed_jobs.rb
111
+ - lib/generators/refinery/dragonfly_delayed_generator.rb
112
+ - lib/refinery/dragonfly_delayed.rb
113
+ - lib/refinery/dragonfly_delayed/engine.rb
114
+ - lib/refinerycms-dragonfly-delayed.rb
115
+ - lib/tasks/refinery/dragonfly_delayed.rake
116
+ homepage:
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.4.5.1
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Delay Dragonfly Jobs for RefineryCMS
140
+ test_files: []