assetable 0.1.10 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/README.rdoc +9 -7
  3. data/app/assets/javascripts/assetable/assetable.js.coffee +16 -0
  4. data/app/assets/javascripts/assetable/assetable_uploader.js.coffee +40 -118
  5. data/app/assets/javascripts/assetable/gallery.js.coffee +12 -10
  6. data/app/assets/javascripts/assetable/uploader.js.coffee +27 -11
  7. data/app/assets/javascripts/vendor/jquery-ui-1.10.3.custom.js +285 -19
  8. data/app/assets/stylesheets/assetable/components/_gallery.css.sass +31 -0
  9. data/app/assets/stylesheets/assetable/components/_uploader.css.sass +2 -2
  10. data/app/assets/stylesheets/assetable/core/_utilities.css.sass +5 -1
  11. data/app/controllers/assetable/assets_controller.rb +19 -10
  12. data/app/controllers/assetable/external_services_controller.rb +9 -5
  13. data/app/helpers/assetable/asset_helper.rb +7 -0
  14. data/app/inputs/gallery_input.rb +28 -0
  15. data/app/inputs/uploader_input.rb +24 -0
  16. data/app/models/asset_attachment.rb +27 -0
  17. data/app/models/gallery.rb +3 -1
  18. data/app/views/assetable/assets/_asset.html.haml +30 -21
  19. data/app/views/assetable/assets/_directions.html.haml +9 -0
  20. data/app/views/assetable/assets/_form.html.haml +3 -5
  21. data/app/views/assetable/assets/_table.html.haml +22 -0
  22. data/app/views/assetable/assets/create.js.erb +7 -0
  23. data/app/views/assetable/assets/edit.js.erb +1 -0
  24. data/app/views/assetable/assets/index.js.erb +18 -0
  25. data/app/views/assetable/assets/insert.js.erb +9 -0
  26. data/app/views/assetable/assets/update.js.erb +2 -0
  27. data/app/views/assetable/external_services/_form.html.haml +3 -2
  28. data/app/views/assetable/external_services/create.js.erb +9 -0
  29. data/app/views/assetable/external_services/new.js.erb +1 -0
  30. data/app/views/assetable/shared/_asset_preview.html.haml +21 -0
  31. data/app/views/assetable/shared/templates/_asset_item.html.haml +29 -0
  32. data/app/views/assetable/shared/templates/_gallery_item.html.haml +42 -0
  33. data/config/initializers/uploader_input.rb +1 -1
  34. data/config/routes.rb +3 -1
  35. data/db/migrate/20140220053656_add_sort_order_to_asset_attachments.rb +15 -0
  36. data/lib/assetable.rb +6 -3
  37. data/lib/assetable/{core.rb → active_record/base.rb} +2 -2
  38. data/lib/assetable/inputs/uploaders.rb +27 -0
  39. data/lib/assetable/version.rb +1 -1
  40. metadata +40 -10
  41. data/app/views/assetable/assets/edit.html.haml +0 -1
  42. 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-data-wrapper
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-data-wrapper
151
+ .gallery-uploader .uploader-assets-wrapper
152
152
  +clearfix
153
153
  text-align: left
154
154
 
@@ -2,4 +2,8 @@
2
2
  float: right
3
3
 
4
4
  .pull-left
5
- float: left
5
+ float: left
6
+
7
+ .clearfix,
8
+ .cf
9
+ +clearfix
@@ -1,10 +1,18 @@
1
1
  class Assetable::AssetsController < ActionController::Base
2
2
 
3
- respond_to :html, :json
3
+ respond_to :html, :js
4
4
 
5
5
  def index
6
6
  @assets = Asset.page(params[:page]).per(20)
7
- render json: { success: true, html: render_to_string(partial: "assetable/assets/gallery", locals: {assets: @assets, fieldname: params[:fieldname]})}
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
- render json: { success: true, html: render_to_string(partial: "assetable/assets/asset", locals: { asset: @asset, fieldname: params[:fieldname]})}
35
+ @fieldname = params[:fieldname]
36
+ @uploader_id = params[:uploader_id]
37
+ render :create
28
38
  else
29
- render json: { status: "error", errors: @asset.errors }
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
- if @asset and @asset.errors.empty? and @asset.update_attributes(permitted_params)
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, :json
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
- render json: { success: true, html: render_to_string(partial: "assetable/assets/asset", locals: { asset: @external_service, fieldname: params[:fieldname]})}
22
+ @fieldname = params[:fieldname]
23
+ @uploader_id = params[:uploader_id]
24
+ render :create
21
25
  else
22
- puts "errors:: #{@external_service.errors.full_messages}"
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,7 @@
1
+ module Assetable::AssetHelper
2
+
3
+ def asset_preview asset
4
+ render partial: "assetable/shared/asset_preview", locals: { asset: asset }
5
+ end
6
+
7
+ end
@@ -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
@@ -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
- .uploader-preview{:'data-asset-id' => asset.id}
2
-
3
- = link_to asset.filename.to_s, target: "_blank" do
4
- - if asset.image?
5
- = image_tag asset.filename.preview.to_s, class: "uploader-preview"
6
- - elsif asset.document?
7
- = image_tag "assetable/icons/icon-#{asset.extension}.png", class: "uploader-preview"
8
- - elsif asset.video?
9
- = image_tag "assetable/icons/icon-mp4.png", class: "uploader-preview"
10
- - elsif asset.external_service?
11
- - if asset.has_icon?
12
- = image_tag "assetable/icons/#{asset.icon}", class: "uploader-preview"
13
- - else
14
- = image_tag "assetable/icons/icon-document.png", class: "uploader-preview"
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
- %span.uploader-name= asset.name
17
- .uploader-size-and-actions
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
- = hidden_field_tag(fieldname, asset.id)
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, @asset], url: assetable_asset_path(@asset, asset_type: @asset.type), remote: true, html: {class: "form-edit-asset"} do |f|
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();
@@ -0,0 +1,2 @@
1
+ $('div.uploader-preview[data-asset-id="<%= @asset.id %>"]').find('.uploader-asset-details').replaceWith('<%= j render partial: "assetable/shared/asset_preview", locals: {asset: @asset} %>');
2
+ $('.assetable-modal-edit-asset').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, @external_service], remote: true do |f|
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, params[: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