create a middleware for serving fonts (solve cross domain issue) + add cache for consume liquid tag + fix image picker

This commit is contained in:
dinedine 2010-10-11 16:26:46 +02:00
parent 86ac74e290
commit 54063d6b46
17 changed files with 138 additions and 39 deletions

View File

@ -4,6 +4,7 @@ module Admin
include ActionView::Helpers::SanitizeHelper
extend ActionView::Helpers::SanitizeHelper::ClassMethods
include ActionView::Helpers::TextHelper
include ActionView::Helpers::NumberHelper
sections 'settings', 'theme_assets'
@ -15,6 +16,7 @@ module Admin
@js_and_css_assets = (@assets[:javascripts] || []) + (@assets[:stylesheets] || [])
if request.xhr?
@images = @assets[:images]
render :action => 'images', :layout => false and return
else
@snippets = current_site.snippets.order_by([[:name, :asc]]).all.to_a
@ -33,9 +35,10 @@ module Admin
success.json do
render :json => {
:status => 'success',
:name => truncate(@theme_asset.slug, :length => 22),
:slug => @theme_asset.slug,
:url => @theme_asset.source.url
:url => @theme_asset.source.url,
:local_path => @theme_asset.local_path(true),
:size => number_to_human_size(@theme_asset.size),
:date => l(@theme_asset.updated_at, :format => :short)
}
end
failure.json { render :json => { :status => 'error' } }

View File

@ -49,6 +49,14 @@ class ThemeAsset
self.stylesheet? || self.javascript?
end
def local_path(short = false)
if short
self.read_attribute(:local_path).gsub(/^#{self.content_type.pluralize}\//, '')
else
self.read_attribute(:local_path)
end
end
def plain_text_name
if not @plain_text_name_changed
@plain_text_name ||= self.safe_source_filename

View File

@ -1,10 +1,13 @@
%li{ :class => "#{'hidden' if asset.hidden?}" }
- edit = local_assigns.key?(:edit) ? edit : true
%li{ :class => "#{asset.new_record? ? 'new-asset' : 'asset'} #{'hidden' if asset.hidden?}" }
%em
%strong= link_to asset.local_path, edit_admin_theme_asset_path(asset)
%strong= link_to asset.local_path(!edit), edit ? edit_admin_theme_asset_path(asset) : asset.source.url, :'data-local-path' => asset.local_path
.more
%span.size= number_to_human_size(asset.size)
—
%span!= t('.updated_at')
= l asset.updated_at, :format => :short
%span.date= l asset.updated_at, :format => :short
- if edit
= link_to image_tag('admin/list/icons/trash.png'), admin_theme_asset_path(asset), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete

View File

@ -4,12 +4,12 @@
.actions
= admin_button_tag t('admin.theme_assets.index.new'), admin_theme_assets_url(:json), :class => 'button small add', :id => 'upload-link'
- if @image_assets.empty?
- if @images.empty?
%p.no-items!= t('.no_items')
%ul.assets
= render 'asset', :asset => current_site.theme_assets.build, :edit => false
%ul.list.theme-assets
= render 'asset', :asset => current_site.theme_assets.build(:updated_at => Time.now, :local_path => 'images/new.jpg', :content_type => 'image'), :edit => false
= render :partial => 'asset', :collection => @image_assets, :locals => { :per_row => 3, :edit => false }
= render :partial => 'asset', :collection => @images, :locals => { :edit => false }
%li.clear

View File

@ -46,5 +46,8 @@ module Locomotive
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters << :password
config.middleware.insert_after ::ActionDispatch::Static, '::Locomotive::Middlewares::Fonts', :path => %r{^/fonts}
# config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware'
end
end

View File

@ -4,14 +4,14 @@ Locomotive::Application.configure do
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
config.cache_classes = true # false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_controller.perform_caching = true #false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false

View File

@ -38,7 +38,8 @@ x snippet dependencies => do not work correctly
x mask internal asset_collections
x refactor ui for the theme assets page
x fix assets liquid tags / filters
- proxy for fonts
x upload and insert new images in a css or js from the ui is broken
x proxy for fonts (http://markevans.github.com/dragonfly/file.Rails3.html)
- fix tests
- order yaml file (http://www.ruby-forum.com/topic/120295)
- global regions: keyword in editable element (http://www.mongodb.org/display/DOCS/Updating)

View File

@ -1,4 +1,3 @@
# require 'locomotive/patches'
require 'locomotive/configuration'
require 'locomotive/logger'
require 'locomotive/liquid'
@ -14,6 +13,7 @@ require 'locomotive/regexps'
require 'locomotive/render'
require 'locomotive/import'
require 'locomotive/delayed_job'
require 'locomotive/middlewares'
require 'mongo_session_store/mongoid'

View File

@ -9,13 +9,17 @@ module Locomotive
return '' if input.nil?
unless input =~ /^(\/|http:)/
stylesheet = ThemeAsset.new(:site => @context.registers[:site], :folder => 'stylesheets')
input = '/' + ThemeAssetUploader.new(stylesheet).store_path(input)
segments = "stylesheets/#{input}".split('/')
filename, folder = segments.pop, segments.join('/')
stylesheet = ThemeAsset.new(:site => @context.registers[:site], :folder => folder)
input = '/' + ThemeAssetUploader.new(stylesheet).store_path(filename)
end
# puts "stylesheet_tag context ? #{@context}"
input = "#{input}.css" unless input.ends_with?('.css')
%{<link href="#{input}" media="screen" rel="stylesheet" type="text/css" />}
end
@ -25,20 +29,39 @@ module Locomotive
return '' if input.nil?
unless input =~ /^(\/|http:)/
javascript = ThemeAsset.new(:site => @context.registers[:site], :folder => 'javascripts')
input = '/' + ThemeAssetUploader.new(javascript).store_path(input)
segments = "javascripts/#{input}".split('/')
filename, folder = segments.pop, segments.join('/')
javascript = ThemeAsset.new(:site => @context.registers[:site], :folder => folder)
input = '/' + ThemeAssetUploader.new(javascript).store_path(filename)
end
input = "#{input}.js" unless input.ends_with?('.js')
%{<script src="#{input}" type="text/javascript"></script>}
end
def theme_image_url(input)
return '' if input.nil?
input = "images/#{input}" unless input.starts_with?('/')
segments = input.split('/')
filename, folder = segments.pop, segments.join('/')
image = ThemeAsset.new(:site => @context.registers[:site], :folder => folder)
'/' + ThemeAssetUploader.new(image).store_path(filename)
end
# Write an image tag
# input: url of the image OR asset drop
def image_tag(input, *args)
image_options = inline_options(args_to_options(args))
"<img src=\"#{File.join('/', get_path_from_asset(input))}\" #{image_options}/>"
"<img src=\"#{File.join('/', get_url_from_asset(input))}\" #{image_options}/>"
end
# Embed a flash movie into a page
@ -46,7 +69,7 @@ module Locomotive
# width: width (in pixel or in %) of the embedded movie
# height: height (in pixel or in %) of the embedded movie
def flash_tag(input, *args)
path = get_path_from_asset(input)
path = get_url_from_asset(input)
embed_options = inline_options(args_to_options(args))
%{
<object #{embed_options}>
@ -114,9 +137,9 @@ module Locomotive
(options.stringify_keys.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
end
# Get the path to be used in html tags such as image_tag, flash_tag, ...etc
# Get the url to be used in html tags such as image_tag, flash_tag, ...etc
# input: url (String) OR asset drop
def get_path_from_asset(input)
def get_url_from_asset(input)
input.respond_to?(:url) ? input.url : input
end
end

View File

@ -5,7 +5,7 @@ module Locomotive
#
# Usage:
#
# {% consume blog from 'http://nocoffee.tumblr.com/api/read.json?num=3' username: 'john', password: 'easy', format: 'json' %}
# {% consume blog from 'http://nocoffee.tumblr.com/api/read.json?num=3' username: 'john', password: 'easy', format: 'json', expires_in: 3000 %}
# {% for post in blog.posts %}
# {{ post.title }}
# {% endfor %}
@ -23,6 +23,8 @@ module Locomotive
markup.scan(::Liquid::TagAttributes) do |key, value|
@options[key] = value if key != 'http'
end
@expires_in = (@options.delete('expires_in') || 0).to_i
@cache_key = Digest::SHA1.hexdigest(@target)
else
raise ::Liquid::SyntaxError.new("Syntax Error in 'consume' - Valid syntax: consume <var> from \"<url>\" [username: value, password: value]")
end
@ -31,12 +33,20 @@ module Locomotive
end
def render(context)
render_all_and_cache_it(context)
end
protected
def render_all_and_cache_it(context)
Rails.cache.fetch(@cache_key, :expires_in => @expires_in) do
context.stack do
context.scopes.last[@target.to_s] = Locomotive::Httparty::Webservice.consume(@url, @options.symbolize_keys)
render_all(@nodelist, context)
end
end
end
end

View File

@ -0,0 +1 @@
require 'locomotive/middlewares/fonts'

View File

@ -0,0 +1,44 @@
require 'rack/utils'
module Locomotive
module Middlewares
class Fonts
include Rack::Utils
def initialize(app, opts = {})
@app = app
@path_regexp = opts[:path] || %r{^/fonts/}
@file_server = ::Rack::File.new(opts[:root] || "#{Rails.root}/public")
@expires_in = opts[:expires_in] || 24.hour
end
def call(env)
if env["PATH_INFO"] =~ @path_regexp
site = fetch_site(env['SERVER_NAME'])
if site.nil?
@app.call(env)
else
env["PATH_INFO"] = ::File.join('/', 'sites', site.id.to_s, 'theme', env["PATH_INFO"])
response = @file_server.call(env)
response[1]['Cache-Control'] = "public; max-age=#{@expires_in}" # varnish
response
end
else
@app.call(env)
end
end
protected
def fetch_site(domain_name)
Rails.cache.fetch(domain_name, :expires_in => @expires_in) do
Site.match_domain(domain_name).first
end
end
end
end
end

View File

@ -56,7 +56,7 @@ module Locomotive
'asset_collections' => Locomotive::Liquid::Drops::AssetCollections.new,
'stylesheets' => Locomotive::Liquid::Drops::ThemeAssets::Stylesheets.new,
'javascripts' => Locomotive::Liquid::Drops::ThemeAssets::Javascripts.new,
'images' => Locomotive::Liquid::Drops::ThemeAssets::Images.new,
'theme_images' => Locomotive::Liquid::Drops::ThemeAssets::Images.new,
'contents' => Locomotive::Liquid::Drops::Contents.new,
'current_page' => self.params[:page]
}

View File

@ -80,7 +80,7 @@ $(document).ready(function() {
if (typeof $.fn.imagepicker != 'undefined')
$('a#image-picker-link').imagepicker({
insertFn: function(link) {
return "{{ theme_images." + link.attr('data-slug') + " }}";
return "{{ '" + link.attr('data-local-path') + "' | theme_image_url }}";
}
});

View File

@ -47,13 +47,13 @@ $.fn.imagepicker = function(options) {
.insertBefore($('.asset-picker ul li.clear'))
.addClass('asset');
asset.find('h4 a').attr('href', json.url)
.attr('data-slug', json.slug)
.attr('data-shortcut-url', json.shortcut_url)
.html(json.name).bind('click', function(e) {
asset.find('strong a').attr('href', json.url)
.attr('data-local-path', json.local_path)
.html(json.local_path).bind('click', function(e) {
copyLinkToEditor($(this), e);
});
asset.find('.image .inside img').attr('src', json.vignette_url);
asset.find('.more .size').html(json.size);
asset.find('.more .date').html(json.date);
if ($('.asset-picker ul li.asset').length % 3 == 0)
asset.addClass('last');
@ -74,7 +74,7 @@ $.fn.imagepicker = function(options) {
'onComplete': function() {
setupUploader();
$('ul.assets h4 a').bind('click', function(e) { copyLinkToEditor($(this), e); });
$('ul.theme-assets strong a').bind('click', function(e) { copyLinkToEditor($(this), e); });
}
});
});

View File

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

View File

@ -49,7 +49,7 @@
/* ___ asset picker ___ */
div.asset-picker { width: 470px; position: relative; }
div.asset-picker { width: 720px; position: relative; }
div.asset-picker .actions { position: absolute; right: 4px; top: 0px; }
div.asset-picker p.no-items { background-image: url("/images/admin/list/none-small.png"); }
@ -57,6 +57,9 @@ div.asset-picker p.no-items { background-image: url("/images/admin/list/none-sma
div.asset-picker ul { overflow: auto; height: 471px; }
div.asset-picker ul li.new-asset { display: none; }
div.asset-picker ul { margin: 0px; }
div.asset-picker ul li .more { top: 8px; }
/* ___ custom fields ___ */
#edit-custom-field {