assetable 0.1.10 → 0.2.1
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 +8 -8
- data/README.rdoc +9 -7
- data/app/assets/javascripts/assetable/assetable.js.coffee +16 -0
- data/app/assets/javascripts/assetable/assetable_uploader.js.coffee +40 -118
- data/app/assets/javascripts/assetable/gallery.js.coffee +12 -10
- data/app/assets/javascripts/assetable/uploader.js.coffee +27 -11
- data/app/assets/javascripts/vendor/jquery-ui-1.10.3.custom.js +285 -19
- data/app/assets/stylesheets/assetable/components/_gallery.css.sass +31 -0
- data/app/assets/stylesheets/assetable/components/_uploader.css.sass +2 -2
- data/app/assets/stylesheets/assetable/core/_utilities.css.sass +5 -1
- data/app/controllers/assetable/assets_controller.rb +19 -10
- data/app/controllers/assetable/external_services_controller.rb +9 -5
- data/app/helpers/assetable/asset_helper.rb +7 -0
- data/app/inputs/gallery_input.rb +28 -0
- data/app/inputs/uploader_input.rb +24 -0
- data/app/models/asset_attachment.rb +27 -0
- data/app/models/gallery.rb +3 -1
- data/app/views/assetable/assets/_asset.html.haml +30 -21
- data/app/views/assetable/assets/_directions.html.haml +9 -0
- data/app/views/assetable/assets/_form.html.haml +3 -5
- data/app/views/assetable/assets/_table.html.haml +22 -0
- data/app/views/assetable/assets/create.js.erb +7 -0
- data/app/views/assetable/assets/edit.js.erb +1 -0
- data/app/views/assetable/assets/index.js.erb +18 -0
- data/app/views/assetable/assets/insert.js.erb +9 -0
- data/app/views/assetable/assets/update.js.erb +2 -0
- data/app/views/assetable/external_services/_form.html.haml +3 -2
- data/app/views/assetable/external_services/create.js.erb +9 -0
- data/app/views/assetable/external_services/new.js.erb +1 -0
- data/app/views/assetable/shared/_asset_preview.html.haml +21 -0
- data/app/views/assetable/shared/templates/_asset_item.html.haml +29 -0
- data/app/views/assetable/shared/templates/_gallery_item.html.haml +42 -0
- data/config/initializers/uploader_input.rb +1 -1
- data/config/routes.rb +3 -1
- data/db/migrate/20140220053656_add_sort_order_to_asset_attachments.rb +15 -0
- data/lib/assetable.rb +6 -3
- data/lib/assetable/{core.rb → active_record/base.rb} +2 -2
- data/lib/assetable/inputs/uploaders.rb +27 -0
- data/lib/assetable/version.rb +1 -1
- metadata +40 -10
- data/app/views/assetable/assets/edit.html.haml +0 -1
- data/app/views/assetable/external_services/new.html.haml +0 -1
@@ -1,3 +1,34 @@
|
|
1
|
+
.assetable-selectable
|
2
|
+
ul
|
3
|
+
+clearfix
|
4
|
+
margin: 0
|
5
|
+
padding: 0
|
6
|
+
|
7
|
+
li
|
8
|
+
float: left
|
9
|
+
list-style: none
|
10
|
+
margin: 0
|
11
|
+
padding: 0
|
12
|
+
|
13
|
+
li.ui-selected
|
14
|
+
background-color: $droppable-bg
|
15
|
+
box-shadow: inset 0 0 0 3px $brand-primary
|
16
|
+
position: relative
|
17
|
+
|
18
|
+
&:after
|
19
|
+
background-color: $brand-primary
|
20
|
+
color: white
|
21
|
+
content: "✓"
|
22
|
+
font-weight: bold
|
23
|
+
right: 0
|
24
|
+
padding: 8px 12px
|
25
|
+
position: absolute
|
26
|
+
top: 0
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
1
32
|
// Backdrop dimmer
|
2
33
|
.assetable-gallery-backdrop
|
3
34
|
background-color: rgba(0, 0, 0, .85)
|
@@ -96,7 +96,7 @@
|
|
96
96
|
// Uploader Preview and actions
|
97
97
|
// -------------------------
|
98
98
|
|
99
|
-
.uploader-
|
99
|
+
.uploader-assets-wrapper
|
100
100
|
+clearfix
|
101
101
|
|
102
102
|
div.uploader-preview
|
@@ -148,7 +148,7 @@ div.uploader-preview
|
|
148
148
|
width: 100%
|
149
149
|
|
150
150
|
|
151
|
-
.gallery-uploader .uploader-
|
151
|
+
.gallery-uploader .uploader-assets-wrapper
|
152
152
|
+clearfix
|
153
153
|
text-align: left
|
154
154
|
|
@@ -1,10 +1,18 @@
|
|
1
1
|
class Assetable::AssetsController < ActionController::Base
|
2
2
|
|
3
|
-
respond_to :html, :
|
3
|
+
respond_to :html, :js
|
4
4
|
|
5
5
|
def index
|
6
6
|
@assets = Asset.page(params[:page]).per(20)
|
7
|
-
|
7
|
+
@fieldname = params[:fieldname]
|
8
|
+
@uploader_id = params[:uploader_id]
|
9
|
+
end
|
10
|
+
|
11
|
+
# Insert assets into a gallery or uploader
|
12
|
+
def insert
|
13
|
+
@fieldname = params[:fieldname]
|
14
|
+
@uploader_id = params[:uploader_id]
|
15
|
+
@assets = Asset.find(params[:asset_ids])
|
8
16
|
end
|
9
17
|
|
10
18
|
# Create a new asset
|
@@ -24,23 +32,23 @@ class Assetable::AssetsController < ActionController::Base
|
|
24
32
|
|
25
33
|
# Return
|
26
34
|
if @asset.errors.empty? and @asset.save
|
27
|
-
|
35
|
+
@fieldname = params[:fieldname]
|
36
|
+
@uploader_id = params[:uploader_id]
|
37
|
+
render :create
|
28
38
|
else
|
29
|
-
render
|
39
|
+
render :error
|
30
40
|
end
|
31
41
|
end
|
32
42
|
|
43
|
+
# Edit an asset will return the edit form
|
33
44
|
def edit
|
34
45
|
@asset = Asset.find(params[:id])
|
35
46
|
end
|
36
47
|
|
48
|
+
# Update an asset
|
37
49
|
def update
|
38
50
|
@asset = Asset.find(params[:id])
|
39
|
-
|
40
|
-
render json: { success: true, id: @asset.id, html: render_to_string(partial: "assetable/assets/asset", locals: { asset: @asset, fieldname: params[:fieldname]})}
|
41
|
-
else
|
42
|
-
render json: { status: "error", errors: @external_service.errors.full_messages, html: render_to_string(:edit) }
|
43
|
-
end
|
51
|
+
@asset.update_attributes(permitted_params)
|
44
52
|
end
|
45
53
|
|
46
54
|
# Permitted params for the model
|
@@ -52,7 +60,8 @@ class Assetable::AssetsController < ActionController::Base
|
|
52
60
|
:content_type,
|
53
61
|
:width,
|
54
62
|
:height,
|
55
|
-
:asset_type
|
63
|
+
:asset_type,
|
64
|
+
:ratio
|
56
65
|
)
|
57
66
|
end
|
58
67
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Assetable::ExternalServicesController < ActionController::Base
|
2
2
|
|
3
|
-
respond_to :html, :
|
3
|
+
respond_to :html, :js
|
4
4
|
|
5
5
|
# def index
|
6
6
|
# @assets = Asset.page(params[:page]).per(20)
|
@@ -10,6 +10,8 @@ class Assetable::ExternalServicesController < ActionController::Base
|
|
10
10
|
# New template
|
11
11
|
def new
|
12
12
|
@external_service = ExternalService.new
|
13
|
+
@fieldname = params[:fieldname]
|
14
|
+
@uploader_id = params[:uploader_id]
|
13
15
|
end
|
14
16
|
|
15
17
|
# Create a new external service asset
|
@@ -17,10 +19,11 @@ class Assetable::ExternalServicesController < ActionController::Base
|
|
17
19
|
@external_service = ExternalService.new(permitted_params)
|
18
20
|
|
19
21
|
if @external_service.errors.empty? and @external_service.save
|
20
|
-
|
22
|
+
@fieldname = params[:fieldname]
|
23
|
+
@uploader_id = params[:uploader_id]
|
24
|
+
render :create
|
21
25
|
else
|
22
|
-
|
23
|
-
render json: { status: "error", errors: @external_service.errors.full_messages, html: render_to_string(:new) }
|
26
|
+
render :error
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
@@ -32,7 +35,8 @@ class Assetable::ExternalServicesController < ActionController::Base
|
|
32
35
|
:body,
|
33
36
|
:content_type,
|
34
37
|
:width,
|
35
|
-
:height
|
38
|
+
:height,
|
39
|
+
:uploader_id
|
36
40
|
)
|
37
41
|
end
|
38
42
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class GalleryInput < SimpleForm::Inputs::FileInput
|
2
|
+
|
3
|
+
include Assetable::Uploaders
|
4
|
+
|
5
|
+
def input
|
6
|
+
# TODO:: Find a better way to do this
|
7
|
+
fieldname = "#{object_name}[#{attribute_name}_attributes][asset_attachments_attributes]"
|
8
|
+
|
9
|
+
# This is the hidden input that identifies which gallery we are saving
|
10
|
+
# otherwise it will create a new gallery each time.
|
11
|
+
hidden_input = template.hidden_field_tag("#{object_name}[#{attribute_name}_attributes][id]", (object.send(attribute_name).present? ? object.send(attribute_name).id : ""))
|
12
|
+
|
13
|
+
# This is the hidden inputs for the uploader. Each asset added to the
|
14
|
+
# gallery will use this input name
|
15
|
+
gallery_hidden_input = template.hidden_field_tag(fieldname, nil, class: "assetable-uploader-input")
|
16
|
+
|
17
|
+
# Gallery preview
|
18
|
+
preview = gallery_preview(fieldname).html_safe rescue ""
|
19
|
+
|
20
|
+
# Uploader HTML = preview + hidden input
|
21
|
+
uploader_html = template.content_tag(:div, (gallery_hidden_input + preview), class: "uploader-assets-wrapper")
|
22
|
+
|
23
|
+
# Create and return the uploader html
|
24
|
+
uploader_wrapper = template.content_tag :div, (uploader_html + hidden_input + directions_html.html_safe), class: "gallery-uploader"
|
25
|
+
return uploader_wrapper
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class UploaderInput < SimpleForm::Inputs::FileInput
|
2
|
+
|
3
|
+
include Assetable::Uploaders
|
4
|
+
|
5
|
+
def input
|
6
|
+
# Create the hidden input as fields_for
|
7
|
+
fieldname = "#{object_name}[#{attribute_name}_association_attributes][asset_id]"
|
8
|
+
|
9
|
+
# For has_one uploaders, we'll add a nil valued hidden field so that we can
|
10
|
+
# remove an image (similar to how checkboxes work)
|
11
|
+
hidden_field = template.hidden_field_tag(fieldname, nil, class: "assetable-uploader-input")
|
12
|
+
|
13
|
+
# Asset preview
|
14
|
+
preview = asset_preview(object.send("#{attribute_name}"), :asset, fieldname)
|
15
|
+
|
16
|
+
# Uploader HTML = preview + hidden input
|
17
|
+
uploader_html = template.content_tag(:div, (hidden_field + preview.html_safe), class: "uploader-assets-wrapper")
|
18
|
+
|
19
|
+
# Create and return the uploader html
|
20
|
+
uploader_wrapper = template.content_tag :div, (uploader_html + directions_html.html_safe), class: "assetable-uploader"
|
21
|
+
return uploader_wrapper
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -1,4 +1,31 @@
|
|
1
1
|
class AssetAttachment < ActiveRecord::Base
|
2
|
+
|
2
3
|
belongs_to :asset
|
3
4
|
belongs_to :assetable, polymorphic: true
|
5
|
+
|
6
|
+
before_validation :ensure_name_is_not_blank
|
7
|
+
before_save :set_sort_order
|
8
|
+
|
9
|
+
# Is the asset_attachment attached to a gallery?
|
10
|
+
def gallery?
|
11
|
+
assetable_type.downcase == "gallery"
|
12
|
+
end
|
13
|
+
|
14
|
+
def gallery
|
15
|
+
assetable
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Ensure the name is not blank to avoid unique indexes on the name
|
22
|
+
# If it's blank, let's set it to nil
|
23
|
+
def ensure_name_is_not_blank
|
24
|
+
name = nil if name.blank?
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_sort_order
|
28
|
+
sort_order = assetable.asset_attachments.size if gallery? and sort_order.blank?
|
29
|
+
end
|
30
|
+
|
4
31
|
end
|
data/app/models/gallery.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
class Gallery < ActiveRecord::Base
|
2
2
|
|
3
3
|
belongs_to :galleryable, polymorphic: true
|
4
|
-
has_many :asset_attachments, as: :assetable, dependent: :destroy
|
4
|
+
has_many :asset_attachments, -> { order('sort_order asc') }, as: :assetable, dependent: :destroy
|
5
5
|
has_many :assets, through: :asset_attachments
|
6
6
|
|
7
|
+
accepts_nested_attributes_for :asset_attachments, allow_destroy: true
|
8
|
+
|
7
9
|
end
|
@@ -1,23 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
/ = asset_preview(asset)
|
2
|
+
/ - if local_assigns.has_key? :fieldname
|
3
|
+
/ = hidden_field_tag(fieldname, asset.id)
|
4
|
+
|
5
|
+
- if asset.present?
|
6
|
+
.uploader-preview{:'data-asset-id' => asset.id}
|
7
|
+
= link_to asset.filename.to_s, target: "_blank" do
|
8
|
+
- if asset.image?
|
9
|
+
= image_tag asset.filename.preview.to_s, class: "uploader-preview"
|
10
|
+
- elsif asset.document?
|
11
|
+
= image_tag "assetable/icons/icon-#{asset.extension}.png", class: "uploader-preview"
|
12
|
+
- elsif asset.video?
|
13
|
+
= image_tag "assetable/icons/icon-mp4.png", class: "uploader-preview"
|
14
|
+
- elsif asset.external_service?
|
15
|
+
- if asset.has_icon?
|
16
|
+
= image_tag "assetable/icons/#{asset.icon}", class: "uploader-preview"
|
17
|
+
- else
|
18
|
+
= image_tag "assetable/icons/icon-document.png", class: "uploader-preview"
|
19
|
+
|
20
|
+
%span.uploader-name= asset.name
|
21
|
+
.uploader-size-and-actions
|
22
|
+
%span.uploader-size= number_to_human_size(asset.file_size)
|
23
|
+
|
24
|
+
.uploader-actions
|
25
|
+
= link_to "delete", "#", class: "btn-uploader btn-uploader-remove-asset"
|
26
|
+
= link_to "edit", Rails.application.routes.url_helpers.edit_assetable_asset_path(asset.id), class: "btn-uploader btn-uploader-edit-asset", remote: true
|
15
27
|
|
16
|
-
|
17
|
-
|
18
|
-
%span.uploader-size= number_to_human_size(asset.file_size)
|
19
|
-
.uploader-actions
|
20
|
-
= link_to "delete", "#", class: "btn-uploader btn-uploader-remove-asset"
|
21
|
-
= link_to "edit", edit_assetable_asset_path(asset), class: "btn-uploader btn-uploader-edit-asset"
|
28
|
+
- if local_assigns.has_key? :fieldname
|
29
|
+
= hidden_field_tag(fieldname, asset.id, id: nil)
|
22
30
|
|
23
|
-
|
31
|
+
- else
|
32
|
+
.uploader-preview
|
@@ -0,0 +1,9 @@
|
|
1
|
+
.uploader-directions.drop-element
|
2
|
+
.uploader-directions-image
|
3
|
+
.uploader-directions-copy
|
4
|
+
= link_to "select file", "#", class: "browse-btn"
|
5
|
+
or
|
6
|
+
= link_to "add a third party service", Rails.application.routes.url_helpers.new_assetable_external_service_path, class: "btn-third-party", remote: true
|
7
|
+
|
8
|
+
/ or
|
9
|
+
/ = link_to "select from gallery", Rails.application.routes.url_helpers.assetable_assets_path(fieldname: fieldname, uploader_id: id), remote: true
|
@@ -1,14 +1,12 @@
|
|
1
|
-
.assetable-assets.assetable-modal.modal.fade
|
1
|
+
.assetable-assets.assetable-modal.modal.fade.assetable-modal-edit-asset
|
2
2
|
.modal-dialog
|
3
3
|
.modal-content
|
4
|
-
= form_for [:assetable,
|
4
|
+
= form_for [:assetable, asset], url: assetable_asset_path(asset, asset_type: asset.type), remote: true, html: {class: "form-edit-asset"} do |f|
|
5
5
|
.modal-header
|
6
6
|
%button.close{"aria-hidden" => "true", "data-dismiss" => "modal", type: "button"} ×
|
7
7
|
%h4.modal-title Asset
|
8
8
|
.modal-body
|
9
|
-
|
10
|
-
= hidden_field_tag :fieldname, params[:fieldname]
|
11
|
-
|
9
|
+
|
12
10
|
.form-group
|
13
11
|
= f.label :name
|
14
12
|
= f.text_field :name, class: "form-control input-fluid", required: true
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.assetable-assets.assetable-modal.modal.fade.assetable-modal-index
|
2
|
+
.modal-dialog
|
3
|
+
= form_tag insert_assetable_assets_path, remote: true do |f|
|
4
|
+
.modal-content
|
5
|
+
.modal-header
|
6
|
+
%button.close{"aria-hidden" => "true", "data-dismiss" => "modal", type: "button"} ×
|
7
|
+
%h4.modal-title Asset Gallery
|
8
|
+
.modal-body.clearfix
|
9
|
+
|
10
|
+
= hidden_field_tag :fieldname, fieldname
|
11
|
+
= hidden_field_tag :uploader_id, uploader_id
|
12
|
+
|
13
|
+
.assetable-selectable
|
14
|
+
%ul
|
15
|
+
- assets.each do |asset|
|
16
|
+
%li
|
17
|
+
= render partial: "asset", locals: {asset: asset}
|
18
|
+
= check_box_tag 'asset_ids[]', asset.id, false, id: "asset_id_#{asset.id}", style: 'visibility: hidden'
|
19
|
+
|
20
|
+
.modal-footer
|
21
|
+
= button_tag "Cancel", class: "btn btn-default", :'data-dismiss' => "modal", type: "button"
|
22
|
+
= button_tag "Insert", type: :submit, class: "btn btn-primary"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
var uploader = $('#<%= @uploader_id %>');
|
2
|
+
|
3
|
+
if (uploader.hasClass("gallery-uploader")) {
|
4
|
+
$('#<%= @uploader_id %>').find('.uploader-assets-wrapper').append('<%= j render partial: "assetable/shared/templates/gallery_item", locals: { asset: @asset, fieldname: @fieldname } %>');
|
5
|
+
} else {
|
6
|
+
$('#<%= @uploader_id %>').find('.uploader-assets-wrapper').html('<%= j render partial: "assetable/shared/templates/asset_item", locals: { asset: @asset, fieldname: @fieldname } %>');
|
7
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
$('<%= j render partial: 'form', locals: {asset: @asset} %>').modal();
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$('<%= j render partial: "table", locals: { assets: @assets, fieldname: @fieldname, uploader_id: @uploader_id } %>').modal();
|
2
|
+
|
3
|
+
$( ".assetable-selectable" ).selectable({
|
4
|
+
filter: 'li',
|
5
|
+
|
6
|
+
selected: function(event,ui) {
|
7
|
+
$( ".ui-selected", this ).each(function(a,b) {
|
8
|
+
$('input[type="checkbox"]',b).attr('checked',true);
|
9
|
+
});
|
10
|
+
},
|
11
|
+
|
12
|
+
unselected: function(event,ui) {
|
13
|
+
$('input[type="checkbox"]',this).attr('checked',false);
|
14
|
+
$( ".ui-selected", this ).each(function(a,b) {
|
15
|
+
$('input[type="checkbox"]',b).attr('checked',true);
|
16
|
+
});
|
17
|
+
}
|
18
|
+
});
|
@@ -0,0 +1,9 @@
|
|
1
|
+
var uploader = $('#<%= @uploader_id %>');
|
2
|
+
|
3
|
+
if (uploader.hasClass("gallery-uploader")) {
|
4
|
+
$('#<%= @uploader_id %>').find('.uploader-assets-wrapper').append('<%= j render partial: "assetable/shared/templates/gallery_item", collection: @assets, locals: {fieldname: @fieldname} %>');
|
5
|
+
} else {
|
6
|
+
$('#<%= @uploader_id %>').find('.uploader-assets-wrapper').html('<%= j render partial: "assetable/shared/templates/asset_item", locals: { asset: @assets.first, fieldname: @fieldname } %>');
|
7
|
+
};
|
8
|
+
|
9
|
+
$('.assetable-modal-index').modal('hide').remove();
|
@@ -1,13 +1,14 @@
|
|
1
1
|
.assetable-external-services.assetable-modal.modal.fade
|
2
2
|
.modal-dialog
|
3
3
|
.modal-content
|
4
|
-
= form_for [:assetable,
|
4
|
+
= form_for [:assetable, external_service], remote: true do |f|
|
5
5
|
.modal-header
|
6
6
|
%button.close{"aria-hidden" => "true", "data-dismiss" => "modal", type: "button"} ×
|
7
7
|
%h4.modal-title Third Party Service
|
8
8
|
.modal-body
|
9
9
|
|
10
|
-
= hidden_field_tag :fieldname,
|
10
|
+
= hidden_field_tag :fieldname, fieldname
|
11
|
+
= hidden_field_tag :uploader_id, uploader_id
|
11
12
|
|
12
13
|
.form-group
|
13
14
|
= f.label :name
|