patch mongoid to enable the limit option for embedded collections + ui widget to allow more than 5 custom models in the content section

This commit is contained in:
did 2011-03-08 16:05:07 +01:00
parent c3cc358934
commit e4b34eac3f
11 changed files with 211 additions and 73 deletions

View File

@ -21,14 +21,13 @@ gem 'rmagick', '2.12.2'
gem 'locomotive_carrierwave', '0.5.0.1.beta3', :require => 'carrierwave'
gem 'custom_fields', '1.0.0.beta.5'
# gem 'custom_fields', :path => '../gems/custom_fields'
gem 'fog', '0.3.7'
gem 'mimetype-fu'
gem 'actionmailer-with-request'
gem 'heroku'
gem 'heroku', '1.18.2'
gem 'httparty', '>= 0.6.1'
gem 'RedCloth', '4.2.7'
gem 'delayed_job', '2.1.2'
gem 'delayed_job', '2.1.4'
gem 'delayed_job_mongoid', '1.0.2'
gem 'rubyzip'
gem 'locomotive_jammit-s3', :require => 'jammit-s3'

View File

@ -83,7 +83,7 @@ GEM
mongoid (~> 2.0.0.rc.7)
daemons (1.1.0)
database_cleaner (0.6.4)
delayed_job (2.1.2)
delayed_job (2.1.4)
activesupport (~> 3.0)
daemons
delayed_job_mongoid (1.0.2)
@ -121,10 +121,10 @@ GEM
growl-glue (1.0.7)
haml (3.0.25)
has_scope (0.5.0)
heroku (1.6.3)
json (>= 1.1.0)
launchy (>= 0.3.2)
rest-client (>= 1.2.0, < 2.0.0)
heroku (1.18.2)
json (~> 1.5.1)
launchy (~> 0.3.2)
rest-client (>= 1.4.0, < 1.7.0)
httparty (0.7.4)
crack (= 0.1.8)
i18n (0.5.0)
@ -137,7 +137,7 @@ GEM
json (1.5.1)
json_pure (1.4.6)
kgio (2.3.2)
launchy (0.4.0)
launchy (0.3.7)
configuration (>= 0.0.5)
rake (>= 0.8.1)
linecache (0.43)
@ -266,7 +266,7 @@ DEPENDENCIES
cucumber-rails
custom_fields (= 1.0.0.beta.5)
database_cleaner
delayed_job (= 2.1.2)
delayed_job (= 2.1.4)
delayed_job_mongoid (= 1.0.2)
devise (= 1.1.3)
factory_girl_rails
@ -274,7 +274,7 @@ DEPENDENCIES
formtastic (~> 1.2.3)
growl-glue
haml (= 3.0.25)
heroku
heroku (= 1.18.2)
httparty (>= 0.6.1)
inherited_resources (~> 1.1.2)
launchy

View File

@ -0,0 +1,62 @@
module Admin::ContentTypesHelper
MAX_DISPLAYED_CONTENTS = 4
def fetch_content_types
return @content_types if @content_types
@content_types = current_site.content_types.ordered.
limit(:contents => Locomotive.config.lastest_items_nb).
only(:name, :slug, :highlighted_field_name, :updated_at).to_a
if @content_type && @content_type.persisted? && @content_types.index(@content_type) >= MAX_DISPLAYED_CONTENTS
@content_types.delete(@content_type)
@content_types.insert(0, @content_type)
end
@content_types
end
def each_content_type_menu_item(which = :first, &block)
types = fetch_content_types
sliced = []
if which == :first
sliced = types[0..MAX_DISPLAYED_CONTENTS - 1]
elsif types.size > MAX_DISPLAYED_CONTENTS
sliced = types[MAX_DISPLAYED_CONTENTS, types.size - MAX_DISPLAYED_CONTENTS]
end
return [] if sliced.empty?
sliced.each do |content_type|
next if content_type.new_record?
item_on = (content_type.slug == @content_type.slug) rescue nil
label = truncate(content_type.name, :length => 15)
url = admin_contents_url(content_type.slug)
css = @content_type && content_type.slug == @content_type.slug ? 'on' : ''
html = admin_submenu_item(label, url, :i18n => false, :css => css) do
yield(content_type)
end
haml_concat(html)
end
end
def other_content_types(&block)
types = fetch_content_types
if types.size > MAX_DISPLAYED_CONTENTS
sliced = types[MAX_DISPLAYED_CONTENTS, types.size - MAX_DISPLAYED_CONTENTS]
html = admin_submenu_item('...', '#', :i18n => false) do
yield(sliced)
end
haml_concat(html)
end
end
end

View File

@ -21,7 +21,8 @@ class ContentType
end
## named scopes ##
scope :first_by_slug, lambda { |slug| where(:slug => slug) }
scope :ordered, :order_by => :updated_at.desc
## indexes ##
index [[:site_id, Mongo::ASCENDING], [:slug, Mongo::ASCENDING]]

View File

@ -10,10 +10,7 @@
= link_to truncate(page.title, :length => 25), edit_admin_page_url(page)
%span= time_ago_in_words(page.updated_at)
- current_site.content_types.to_a.each do |content_type|
- next if content_type.new_record?
- item_on = (content_type.slug == @content_type.slug) rescue nil
= admin_submenu_item content_type.name, admin_contents_url(content_type.slug), :i18n => false, :css => (item_on ? 'on' : '') do
- each_content_type_menu_item do |content_type|
.header
%p= link_to t('admin.contents.index.new'), new_admin_content_url(content_type.slug)
.inner
@ -21,8 +18,15 @@
%ul
- content_type.contents.latest_updated.each do |content|
%li
= link_to truncate(content.send(content_type.highlighted_field_name), :length => 30), edit_admin_content_path(content_type.slug, content)
= link_to truncate(content.send(content_type.highlighted_field_name), :length => 20), edit_admin_content_path(content_type.slug, content)
%span= time_ago_in_words(content.updated_at)
- other_content_types do |content_types|
.inner
%ul.big-links
- content_types.each do |content_type|
%li
= link_to truncate(content_type.name, :length => 20), admin_contents_url(content_type.slug)
.action
= link_to content_tag(:em) + content_tag(:span, t('admin.content_types.index.new')), new_admin_content_type_url

View File

@ -16,7 +16,7 @@ require 'actionmailer_with_request'
require 'heroku'
require 'httparty'
require 'redcloth'
#require 'delayed_job_mongoid'
require 'delayed_job_mongoid'
require 'zip/zipfilesystem'
require 'jammit-s3'

View File

@ -1,3 +1,91 @@
# encoding: utf-8
require 'mongoid'
## For now, no mongoid monkey patch is required, that is a good thing after all :-)
# Limit feature for embedded documents
module Mongoid #:nodoc:
module Criterion #:nodoc:
module Exclusion
def only(*args)
clone.tap do |crit|
crit.options[:fields] ||= {}
crit.options[:fields][:only] = args.flatten if args.any?
end
end
end
module Optional
# Adds a criterion to the +Criteria+ that specifies the maximum number of
# results to return. This is mostly used in conjunction with <tt>skip()</tt>
# to handle paginated results.
#
# Options:
#
# value: An +Integer+ specifying the max number of results. Defaults to 20.
# hash: A +Hash+ specifying the max number of results for the embedded collections.
#
# Example:
#
# <tt>criteria.limit(100)</tt>
# <tt>criteria.limit(100, { :contents => 5 })</tt>
# <tt>criteria.limit(:contents => 5)</tt>
#
# Returns: <tt>self</tt>
def limit(*args)
clone.tap do |crit|
arguments = args.first || 20
fields = nil # hash of embedded collections
case arguments
when Integer
crit.options[:limit] = arguments
fields = args[1] if args.size > 1
when Hash
fields = arguments
end
if fields
crit.options[:fields] ||= {}
crit.options[:fields][:limit] = fields
end
end
end
end
end
module Contexts #:nodoc:
class Mongo
# Filters the field list. If no fields have been supplied, then it will be
# empty. If fields have been defined then _type will be included as well.
def process_options
fields = options[:fields]
only = fields.delete(:only) if fields
limits = fields.delete(:limit) if fields
# only ?
if only && only.size > 0
only << :_type if !only.include?(:_type)
only.each do |field|
options[:fields].merge!(field => 1)
end
end
# limit for embedded collections ?
if limits && limits.size > 0
limits.each do |field, limit|
options[:fields][field] = { '$slice' => limit }
end
end
options.dup
end
end
end
end

View File

@ -40,7 +40,7 @@ Gem::Specification.new do |s|
s.add_dependency "heroku"
s.add_dependency "httparty", ">= 0.6.1"
s.add_dependency "RedCloth", "4.2.7"
s.add_dependency "delayed_job", "2.1.2"
s.add_dependency "delayed_job", "2.1.4"
s.add_dependency "delayed_job_mongoid", "1.0.2"
s.add_dependency "rubyzip"
s.add_dependency "locomotive_jammit-s3"

View File

@ -8,8 +8,7 @@
position: relative;
top: -1px;
z-index: 998;
min-height: 60px;
width: 950px;
height: 60px;
margin: 0px;
padding: 0 8px;
background: transparent url(/images/admin/menu/shadow.png) repeat-y 0 0;
@ -25,24 +24,12 @@
border-top-right-radius: 3px ;
-moz-border-radius-top-right: 3px ;
-webkit-border-top-right-radius: 3px ;
width: 826px;
padding-right: 124px;
padding-top: 8px;
padding-bottom: 8px;
min-height: 44px; }
#submenu > ul:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden; }
height: 60px; }
#submenu > ul a {
text-decoration: none; }
#submenu > ul > li {
margin: 7px 7px 7px 8px;
height: 30px;
float: left;
position: relative; }
margin: 15px 7px 0 8px;
float: left; }
#submenu > ul > li.hoverable > a span em {
display: inline-block;
background: transparent url(/images/admin/menu/icons.png) no-repeat 0 -16px;
@ -114,9 +101,10 @@
position: absolute;
top: 0px;
right: 22px;
height: 100%;
height: 60px;
padding-left: 20px;
z-index: 1; }
z-index: 1;
background: transparent url(/images/admin/menu/submenu/action-border.png) repeat-y left 0; }
#submenu > .action a {
margin-top: 18px;
display: inline-block;
@ -148,7 +136,7 @@
border-color: black; }
#submenu .popup {
position: absolute;
top: 26px;
top: 42px;
min-width: 250px;
background: #fff;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
@ -197,6 +185,7 @@
color: #8b8d9a;
font-size: 0.7em; }
#submenu .popup ul.big-links {
list-style: none;
margin: 0px; }
#submenu .popup ul.big-links li {
margin: 10px 0; }
@ -207,7 +196,7 @@
padding: 3px 10px;
background: #ebedf4;
font-weight: bold;
font-size: 14px; }
font-size: 0.8em; }
#submenu .popup .footer {
background: #ebedf4;
padding: 8px 16px;
@ -323,7 +312,7 @@ body.contents #submenu > ul {
background: -moz-linear-gradient(0% 100% 90deg, #212229, #1e1e24);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1e1e24), to(#212229)); }
body.contents #submenu > .action {
background: transparent url(/images/admin/menu/submenu/action-border.png) repeat-y left 0; }
background-image: url(/images/admin/menu/submenu/black-action-border.png) !important; }
#menu li.assets a em {
position: relative;

View File

@ -9,8 +9,7 @@
position: relative;
top: -1px;
z-index: 998;
min-height: 60px;
width: 950px;
height: 60px;
margin: 0px;
padding: 0 8px;
background: transparent url(/images/admin/menu/shadow.png) repeat-y 0 0;
@ -18,22 +17,16 @@
/* ___ submenu items ___ */
& > ul {
@include clearfix;
@include reset;
border-top: 1px solid rgba(255, 255, 255, 0.4);
background: transparent url(/images/admin/menu/submenu/shadow.png) repeat-x 0 0;
@include rounded(top-right, 3px);
width: 826px;
padding-right: 124px;
padding-top: 8px;
padding-bottom: 8px;
min-height: 44px;
height: 60px;
& > li {
margin: 7px 7px 7px 8px;
height: 30px;
margin: 15px 7px 0 8px;
float: left;
position: relative;
&.hoverable > a span {
em {
@ -112,9 +105,10 @@
& > .action {
@include absolute-position(top, 0px, right, 22px);
height: 100%;
height: 60px;
padding-left: 20px;
z-index: 1;
background: transparent url(/images/admin/menu/submenu/action-border.png) repeat-y left 0;
a {
margin-top: 18px;
@ -156,7 +150,7 @@
.popup {
position: absolute;
top: 26px;
top: 42px;
min-width: 250px;
background: #fff;
@include box-shadow(0px, 0px, 10px, rgba(0, 0, 0, 0.5));
@ -209,6 +203,7 @@
}
&.big-links {
list-style: none;
margin: 0px;
li {
@ -219,7 +214,7 @@
padding: 3px 10px;
background: #ebedf4;
font-weight: bold;
font-size: 14px;
font-size: 0.8em;
}
}
}
@ -259,7 +254,7 @@
}
& > .action {
background: transparent url(/images/admin/menu/submenu/action-border.png) repeat-y left 0;
background-image: url(/images/admin/menu/submenu/black-action-border.png) !important;
}
}