refactoring theme assets in progress

This commit is contained in:
dinedine 2010-10-10 16:37:34 +02:00
parent ecfa466074
commit 2f4128bf8f
14 changed files with 103 additions and 154 deletions

View File

@ -16,7 +16,8 @@ gem 'rmagick', '2.12.2'
gem 'aws' gem 'aws'
gem 'mimetype-fu', :require => 'mimetype_fu' gem 'mimetype-fu', :require => 'mimetype_fu'
gem 'formtastic-rails3', '1.0.0.beta3', :require => 'formtastic' gem 'formtastic-rails3', '1.0.0.beta3', :require => 'formtastic'
gem 'carrierwave', '0.5.0.beta2' # gem 'carrierwave', '0.5.0.beta2'
gem 'carrierwave', :path => '../gems/carrierwave'
gem 'actionmailer-with-request', :require => 'actionmailer_with_request' gem 'actionmailer-with-request', :require => 'actionmailer_with_request'
gem 'heroku' gem 'heroku'
gem 'httparty', '0.6.1' gem 'httparty', '0.6.1'

View File

@ -11,6 +11,12 @@ GIT
specs: specs:
liquid (2.1.3) liquid (2.1.3)
PATH
remote: /Users/didier/Desktop/NoCoffee/LocomotiveCMS/gems/carrierwave
specs:
carrierwave (0.5.0)
activesupport (~> 3.0)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
specs: specs:
@ -53,8 +59,6 @@ GEM
bson (1.0.4) bson (1.0.4)
bson_ext (1.0.4) bson_ext (1.0.4)
builder (2.1.2) builder (2.1.2)
carrierwave (0.5.0.beta2)
activesupport (>= 3.0.0.beta4)
cgi_multipart_eof_fix (2.5.0) cgi_multipart_eof_fix (2.5.0)
configuration (1.1.0) configuration (1.1.0)
crack (0.1.8) crack (0.1.8)
@ -167,7 +171,7 @@ DEPENDENCIES
actionmailer-with-request actionmailer-with-request
aws aws
bson_ext (= 1.0.4) bson_ext (= 1.0.4)
carrierwave (= 0.5.0.beta2) carrierwave!
cgi_multipart_eof_fix cgi_multipart_eof_fix
custom_fields! custom_fields!
delayed_job (= 2.1.0.pre2) delayed_job (= 2.1.0.pre2)

View File

@ -12,9 +12,6 @@ module Admin
def index def index
@assets = current_site.theme_assets.visible.all.order_by([[:slug, :asc]]).group_by { |a| a.folder.split('/').first.to_sym } @assets = current_site.theme_assets.visible.all.order_by([[:slug, :asc]]).group_by { |a| a.folder.split('/').first.to_sym }
@js_and_css_assets = (@assets[:javascripts] || []) + (@assets[:stylesheets] || []) @js_and_css_assets = (@assets[:javascripts] || []) + (@assets[:stylesheets] || [])
# @non_image_assets = assets.find_all { |a| a.stylesheet? || a.javascript? }
# @image_assets = assets.find_all { |a| a.image? }
# @flash_assets = assets.find_all { |a| a.movie? }
if request.xhr? if request.xhr?
render :action => 'images', :layout => false and return render :action => 'images', :layout => false and return
@ -23,6 +20,11 @@ module Admin
end end
end end
def edit
resource.performing_plain_text = true if resource.stylesheet_or_javascript?
edit!
end
def create def create
params[:theme_asset] = { :source => params[:file] } if params[:file] params[:theme_asset] = { :source => params[:file] } if params[:file]

View File

@ -8,7 +8,6 @@ class ThemeAsset
field :width, :type => Integer field :width, :type => Integer
field :height, :type => Integer field :height, :type => Integer
field :size, :type => Integer field :size, :type => Integer
# field :plain_text
field :folder, :default => nil field :folder, :default => nil
field :hidden, :type => Boolean, :default => false field :hidden, :type => Boolean, :default => false
mount_uploader :source, ThemeAssetUploader mount_uploader :source, ThemeAssetUploader
@ -24,31 +23,25 @@ class ThemeAsset
before_validation :store_plain_text before_validation :store_plain_text
before_validation :sanitize_folder before_validation :sanitize_folder
before_validation :build_local_path before_validation :build_local_path
# before_validation :sanitize_slug
# before_validation :escape_shortcut_urls
# before_save :set_slug
## validations ## ## validations ##
# validate :extname_can_not_be_changed
validates_presence_of :site, :source validates_presence_of :site, :source
# validate :plain_text_name_is_required_if_no_given_source validates_presence_of :plain_text_name, :if => Proc.new { |a| puts "===> performing_plain_text? = #{a.performing_plain_text?}"; a.performing_plain_text? }
validates_presence_of :plain_text_name, :if => Proc.new { |a| a.performing_plain_text? }
# validates_presence_of :slug, :if => Proc.new { |a| a.new_record? && a.performing_plain_text? }
# validates_uniqueness_of :slug, :scope => [:site_id, :content_type, :folder]
validates_uniqueness_of :local_path, :scope => :site_id validates_uniqueness_of :local_path, :scope => :site_id
validates_integrity_of :source validates_integrity_of :source
validate :content_type_can_not_changed
## named scopes ## ## named scopes ##
scope :visible, :where => { :hidden => false } scope :visible, :where => { :hidden => false }
## accessors ## ## accessors ##
attr_accessor :plain_text_name, :plain_text, :performing_plain_text attr_accessor :plain_text_name, :plain_text, :performing_plain_text #, :new_file
## methods ## ## methods ##
# def source=(new_file) # def source=(new_file)
# @new_source = true
# super # super
# @new_source = true
# end # end
%w{movie image stylesheet javascript font}.each do |type| %w{movie image stylesheet javascript font}.each do |type|
@ -66,14 +59,6 @@ class ThemeAsset
@plain_text_name ||= self.safe_source_filename @plain_text_name ||= self.safe_source_filename
end end
@plain_text_name.gsub(/(\.[a-z0-9A-Z]+)$/, '') rescue nil @plain_text_name.gsub(/(\.[a-z0-9A-Z]+)$/, '') rescue nil
#
# @plain_text_name ||= self.safe_source_filename rescue nil if
#
# if @plain_text_name_changed
#
#
# @plain_text_name_changed ? @plain_text_name :
# (@plain_text_name || self.safe_source_filename).gsub(/(\.[a-z0-9A-Z]+)$/, '') rescue nil
end end
def plain_text_name=(name) def plain_text_name=(name)
@ -82,30 +67,20 @@ class ThemeAsset
end end
def plain_text def plain_text
if not @plain_text_changed if not self.performing_plain_text? #not @plain_text_changed
@plain_text ||= self.source.read rescue nil @plain_text ||= self.source.read rescue nil
end end
@plain_text @plain_text
# # self.plain_text = self.source.read if read_attribute(:plain_text).blank?
# # read_attribute(:plain_text)
# else
# nil
# end
end end
def plain_text=(source) # def plain_text=(source)
# @new_source = true # # @plain_text_changed = true
@plain_text_changed = true # # self.performing_plain_text = true unless source.blank?
self.performing_plain_text = true #if self.performing_plain_text.nil? # @plain_text = source
@plain_text = source # end
# write_attribute(:plain_text, source)
end
def performing_plain_text? def performing_plain_text?
Boolean.set(self.performing_plain_text) Boolean.set(self.performing_plain_text) || false
# self.performing_plain_text == true || self.performing_plain_text == '1' || self.performing_plain_text ==
# return true if !self.new_record? && self.stylesheet_or_javascript? && self.errors.empty?
# !(self.performing_plain_text.blank? || self.performing_plain_text == 'false' || self.performing_plain_text == false)
end end
def store_plain_text def store_plain_text
@ -113,28 +88,21 @@ class ThemeAsset
sanitized_source = self.escape_shortcut_urls(self.plain_text) sanitized_source = self.escape_shortcut_urls(self.plain_text)
# puts "================"
# puts self.source.instance_variable_get(:@original_file).inspect
self.source = CarrierWave::SanitizedFile.new({ self.source = CarrierWave::SanitizedFile.new({
:tempfile => StringIO.new(sanitized_source), :tempfile => StringIO.new(sanitized_source),
:filename => "#{self.plain_text_name}.#{self.stylesheet? ? 'css' : 'js'}" :filename => "#{self.plain_text_name}.#{self.stylesheet? ? 'css' : 'js'}"
}) })
end end
# def shortcut_url # ex: /stylesheets/application.css is a shortcut for a theme asset (content_type => stylesheet, slug => 'application')
# File.join(self.content_type.pluralize, "#{self.slug}#{File.extname(self.source_filename)}")
# rescue
# ''
# end
def to_liquid def to_liquid
{ :url => self.source.url }.merge(self.attributes) { :url => self.source.url }.merge(self.attributes)
end end
protected protected
# def new_source?
# @new_source == true
# end
def safe_source_filename def safe_source_filename
self.source_filename || self.source.send(:original_filename) rescue nil self.source_filename || self.source.send(:original_filename) rescue nil
end end
@ -143,7 +111,7 @@ class ThemeAsset
self.folder = self.content_type.pluralize if self.folder.blank? self.folder = self.content_type.pluralize if self.folder.blank?
# no accents, no spaces, no leading and ending trails # no accents, no spaces, no leading and ending trails
self.folder = ActiveSupport::Inflector.transliterate(self.folder).gsub(/(\s)+/, '_').gsub(/^\//, '').gsub(/\/$/, '') self.folder = ActiveSupport::Inflector.transliterate(self.folder).gsub(/(\s)+/, '_').gsub(/^\//, '').gsub(/\/$/, '').downcase
# folder should begin by a root folder # folder should begin by a root folder
if (self.folder =~ /^(stylesheets|javascripts|images|media|fonts)/).nil? if (self.folder =~ /^(stylesheets|javascripts|images|media|fonts)/).nil?
@ -152,7 +120,7 @@ class ThemeAsset
end end
def build_local_path def build_local_path
puts "self.source_filename = #{self.source_filename} / #{self.safe_source_filename} / #{File.join(self.folder, self.safe_source_filename)}" # puts "self.source_filename = #{self.source_filename} / #{self.safe_source_filename} / #{File.join(self.folder, self.safe_source_filename)}"
self.local_path = File.join(self.folder, self.safe_source_filename) self.local_path = File.join(self.folder, self.safe_source_filename)
end end
@ -160,54 +128,19 @@ class ThemeAsset
return if text.blank? return if text.blank?
text.gsub(/[("'](\/(stylesheets|javascripts|images|media)\/((.+)\/)*([a-z_\-0-9]+)\.[a-z]{2,3})[)"']/) do |path| text.gsub(/[("'](\/(stylesheets|javascripts|images|media)\/((.+)\/)*([a-z_\-0-9]+)\.[a-z]{2,3})[)"']/) do |path|
sanitized_path = path.gsub(/[("')]/, '').gsub(/^\//, '')
# puts "\t\t\tfound path = #{sanitized_path}" sanitized_path = path.gsub(/[("')]/, '').gsub(/^\//, '')
if asset = self.site.theme_assets.where(:local_path => sanitized_path).first if asset = self.site.theme_assets.where(:local_path => sanitized_path).first
"#{path.first}#{asset.source.url}#{path.last}" "#{path.first}#{asset.source.url}#{path.last}"
else else
path path
end end
# content_type, slug = url.split('/')[1..-1]
# content_type = content_type.singularize
# slug = slug.split('.').first
# if asset = self.site.theme_assets.where(:content_type => content_type, :slug => slug).first
# asset.source.url
# else
# url
# end
end end
end end
# def plain_text_name_is_required_if_no_given_source def content_type_can_not_changed
# puts "@performing_plain_text = #{self.performing_plain_text?} / #{@plain_text_name} / new_file = #{self.source.inspect}" self.errors.add(:source, :extname_changed) if !self.new_record? && self.content_type_changed?
# if self.performing_plain_text? && @plain_text_name.blank? end
# self.errors.add(:plain_text_name, :blank)
# end
# end
# def sanitize_slug
# self.slug.parameterize! if self.slug.present?
# end
#
# def set_slug
# if self.slug.blank?
# self.slug = File.basename(self.source_filename, File.extname(self.source_filename))
# self.sanitize_slug
# end
# end
#
# def extname_can_not_be_changed
# return if self.new_record? || self.source.file.original_filename.nil?
#
# puts "filename => #{self.source_filename} / source file => #{self.source.file.inspect}"
#
# if File.extname(self.source.file.original_filename) != File.extname(self.source_filename)
# self.errors.add(:source, :extname_changed)
# end
# end
end end

View File

@ -27,11 +27,12 @@ class AssetUploader < CarrierWave::Uploader::Base
process :convert => 'png' process :convert => 'png'
end end
process :set_content_type
process :set_size
process :set_width_and_height process :set_width_and_height
def set_content_type after :cache, :set_size
after :cache, :set_content_type
def set_content_type(*args)
value = :other value = :other
content_type = file.content_type == 'application/octet-stream' ? File.mime_type?(original_filename) : file.content_type content_type = file.content_type == 'application/octet-stream' ? File.mime_type?(original_filename) : file.content_type
@ -48,7 +49,7 @@ class AssetUploader < CarrierWave::Uploader::Base
model.content_type = value model.content_type = value
end end
def set_size def set_size(*args)
model.size = file.size model.size = file.size
end end

View File

@ -6,38 +6,46 @@ class ThemeAssetUploader < AssetUploader
process :set_size process :set_size
process :set_width_and_height process :set_width_and_height
# version :thumb do # after :store, :foo
# process :resize_to_fill => [50, 50]
# process :convert => 'png'
# end
# #
# version :medium do # def filename_was
# process :resize_to_fill => [80, 80] # column = model.send(:_mounter, self.mounted_as).send(:serialization_column)
# process :convert => 'png' # model.send("#{column}_was")
# end # end
# #
# version :preview do # def filename_changed?
# process :resize_to_fit => [880, 1100] # column = model.send(:_mounter, self.mounted_as).send(:serialization_column)
# process :convert => 'png' # model.send("#{column}_changed?")
# end # end
def store_dir def store_dir
File.join('sites', model.site_id.to_s, 'theme', model.folder) File.join('sites', model.site_id.to_s, 'theme', model.folder_was || model.folder)
# File.join('sites', model.site_id.to_s, 'theme', model.content_type.pluralize, model.subfolder || '')
# base = File.join('sites', model.site_id.to_s, 'theme')
# # puts "base = #{base} / #{model.subfolder.inspect}"
# if model.subfolder.blank?
# File.join(base, model.content_type.pluralize)
# else
# File.join(base, model.subfolder)
# end
#
# # "sites/#{model.site_id}/themes/#{model.id}/#{model.content_type.pluralize}"
# File.join("sites/#{model.site_id}/theme", model.subfolder || '', model.content_type.pluralize)
end end
# def store_dir_was
# File.join('sites', model.site_id.to_s, 'theme', model.folder_was)
# end
#
def stale_model?
!model.new_record? && model.folder_changed?
end
#
# def store_dir_was
# File.join('sites', model.site_id.to_s, 'theme', model.folder_was) rescue nil
# end
#
# def store_dir_changed?
# self.store_dir_was && self.store_dir_was != self.store_dir
# end
#
# def store_path_was(for_file=filename)
# File.join([store_dir_was, full_filename(for_file)].compact)
# end
#
# def foo
# "store_dir_was = #{store_dir_was.inspect} / #{store_path_was}"
# end
def extension_white_list def extension_white_list
%w(jpg jpeg gif png css js swf flv eot svg ttf woff) %w(jpg jpeg gif png css js swf flv eot svg ttf woff)
end end

View File

@ -1,17 +1,3 @@
/ - per_row = local_assigns[:per_row] || 6
/ - asset_counter = local_assigns[:asset_counter] || 0
/ - edit = local_assigns.key?(:edit) ? edit : true
/
/ %li{ :class => "#{asset.new_record? ? 'new-asset' : 'asset'} #{'last' if (asset_counter + 1) % per_row == 0}"}
/ %h4= link_to truncate(asset.slug, :length => 18), edit ? edit_admin_theme_asset_path(asset) : asset.source.url, :"data-slug" => asset.slug, :"data-shortcut-url" => asset.shortcut_url
/ .image
/ .inside
/ = vignette_tag(asset)
/ - if edit
/ .actions
/ = link_to image_tag('admin/list/icons/cross.png'), admin_theme_asset_path(asset), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete
%li %li
%em %em
%strong= link_to asset.local_path, edit_admin_theme_asset_path(asset) %strong= link_to asset.local_path, edit_admin_theme_asset_path(asset)

View File

@ -7,7 +7,6 @@
#file-selector{ :class => "selector #{'hidden' if @theme_asset.performing_plain_text?}" } #file-selector{ :class => "selector #{'hidden' if @theme_asset.performing_plain_text?}" }
= f.inputs :name => :information do = f.inputs :name => :information do
= f.input :source = f.input :source
= f.input :slug
- if @theme_asset.new_record? || @theme_asset.stylesheet_or_javascript? - if @theme_asset.new_record? || @theme_asset.stylesheet_or_javascript?
%span.alt %span.alt
@ -18,10 +17,10 @@
= f.inputs :name => :code, :class => 'inputs code' do = f.inputs :name => :code, :class => 'inputs code' do
- if @theme_asset.new_record? - if @theme_asset.new_record?
= f.input :slug = f.input :plain_text_name
= f.custom_input :content_type do = f.custom_input :content_type do
= f.select :content_type, ["stylesheet", "javascript"] = f.select :content_type, %w(stylesheet javascript)
= f.custom_input :plain_text, :css => 'full', :with_label => false do = f.custom_input :plain_text, :css => 'full', :with_label => false do
%code{ :class => (@theme_asset.size && @theme_asset.size > 40000 ? 'nude' : (@theme_asset.content_type || 'stylesheet')) } %code{ :class => (@theme_asset.size && @theme_asset.size > 40000 ? 'nude' : (@theme_asset.content_type || 'stylesheet')) }
@ -32,9 +31,14 @@
%span.alt %span.alt
!= t('admin.theme_assets.form.choose_file') != t('admin.theme_assets.form.choose_file')
- if @theme_asset.image? / - if @theme_asset.image?
= f.foldable_inputs :name => "#{t('formtastic.titles.preview')} #{image_dimensions_and_size(@theme_asset)}", :class => 'preview' do / = f.foldable_inputs :name => "#{t('formtastic.titles.preview')} #{image_dimensions_and_size(@theme_asset)}", :class => 'preview' do
%li / %li
.image / .image
.inside / .inside
= image_tag(@theme_asset.source.url(:preview)) / = image_tag(@theme_asset.source.url(:preview))
= f.foldable_inputs :name => :options do
= f.input :folder
= f.custom_input :hidden, :css => 'toggle' do
= f.check_box :hidden

View File

@ -6,7 +6,7 @@
- content_for :buttons do - content_for :buttons do
= admin_button_tag t('admin.theme_assets.index.new'), new_admin_theme_asset_url, :class => 'new' = admin_button_tag t('admin.theme_assets.index.new'), new_admin_theme_asset_url, :class => 'new'
%p!= t('.help', :url => @theme_asset.source.url, :shortcut_url => @theme_asset.shortcut_url) %p!= t('.help', :url => @theme_asset.source.url)
= semantic_form_for @theme_asset, :url => admin_theme_asset_url(@theme_asset), :html => { :multipart => true, :class => 'save-with-shortcut' } do |form| = semantic_form_for @theme_asset, :url => admin_theme_asset_url(@theme_asset), :html => { :multipart => true, :class => 'save-with-shortcut' } do |form|

View File

@ -173,7 +173,7 @@ en:
help: "You have the choice to either upload any file or to copy/paste a stylesheet or a javascript in plain text." help: "You have the choice to either upload any file or to copy/paste a stylesheet or a javascript in plain text."
edit: edit:
title: "Editing %{file}" title: "Editing %{file}"
help: "You can insert the following shortcut url in your stylesheets: <strong>%{shortcut_url}</strong> OR use the direct url <strong>%{url}</strong>" help: "This asset is accessible from the following url: <strong>%{url}</strong>"
form: form:
picker_link: Insert a file into the code picker_link: Insert a file into the code
choose_file: Choose file choose_file: Choose file

View File

@ -4,8 +4,6 @@ module Locomotive
module Import module Import
class Job class Job
# attr_accessor :theme_file, :site, :enabled
def initialize(theme_file, site = nil, enabled = {}) def initialize(theme_file, site = nil, enabled = {})
raise "Theme zipfile not found" unless File.exists?(theme_file) raise "Theme zipfile not found" unless File.exists?(theme_file)

View File

@ -5,7 +5,7 @@ module Locomotive
def self.process(context) def self.process(context)
site, database = context[:site], context[:database] site, database = context[:site], context[:database]
attributes = database['site'].clone.delete_if { |name, value| %w{pages content_types asset_collections}.include?(name) } attributes = database['site'].clone.delete_if { |name, value| %w{pages assets content_types asset_collections}.include?(name) }
site.attributes = attributes site.attributes = attributes

View File

@ -1,8 +1,8 @@
require 'mongoid' require 'mongoid'
# require 'mongoid/document'
## various patches ## various patches
module Mongoid #:nodoc: module Mongoid #:nodoc:
module Document module Document
def update_child_with_noname(child, clear = false) def update_child_with_noname(child, clear = false)
@ -13,9 +13,21 @@ module Mongoid #:nodoc:
alias_method_chain :update_child, :noname alias_method_chain :update_child, :noname
# module ClassMethods
#
# def instantiate(attrs = nil, allocating = false) # used by carrierwave to back up the original file
# document = super
# document.send(:run_callbacks, :initialize) do
# document
# end
# end
#
# end
end end
end end
module Mongoid #:nodoc: module Mongoid #:nodoc:
module Validations #:nodoc: module Validations #:nodoc:
class AssociatedValidator < ActiveModel::EachValidator class AssociatedValidator < ActiveModel::EachValidator

View File

@ -37,7 +37,7 @@ $(document).ready(function() {
$('a#image-picker-link').imagepicker({ $('a#image-picker-link').imagepicker({
insertFn: function(link) { insertFn: function(link) {
return link.attr('data-shortcut-url'); return link.attr('data-url');
} }
}); });
}); });