assetable 0.1.10 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|