diff --git a/Gemfile b/Gemfile
index 63b0a639..3897723a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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'
diff --git a/Gemfile.lock b/Gemfile.lock
index 305eebd4..0a409d5b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -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
diff --git a/app/helpers/admin/content_types_helper.rb b/app/helpers/admin/content_types_helper.rb
new file mode 100644
index 00000000..f3f35681
--- /dev/null
+++ b/app/helpers/admin/content_types_helper.rb
@@ -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
\ No newline at end of file
diff --git a/app/models/content_type.rb b/app/models/content_type.rb
index fcc41511..7b9ff7c4 100644
--- a/app/models/content_type.rb
+++ b/app/models/content_type.rb
@@ -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]]
diff --git a/app/views/admin/shared/menu/_contents.html.haml b/app/views/admin/shared/menu/_contents.html.haml
index c9fd39e0..106a4080 100644
--- a/app/views/admin/shared/menu/_contents.html.haml
+++ b/app/views/admin/shared/menu/_contents.html.haml
@@ -10,19 +10,23 @@
= 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
- .header
- %p= link_to t('admin.contents.index.new'), new_admin_content_url(content_type.slug)
- .inner
- %h2!= t('admin.contents.index.lastest_items')
- %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)
- %span= time_ago_in_words(content.updated_at)
+ - 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
+ %h2!= t('admin.contents.index.lastest_items')
+ %ul
+ - content_type.contents.latest_updated.each do |content|
+ %li
+ = 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
\ No newline at end of file
diff --git a/lib/locomotive/engine.rb b/lib/locomotive/engine.rb
index 8f50f106..f3254a3f 100644
--- a/lib/locomotive/engine.rb
+++ b/lib/locomotive/engine.rb
@@ -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'
diff --git a/lib/locomotive/liquid/tags/editable/content.rb b/lib/locomotive/liquid/tags/editable/content.rb
index 1964f92a..280d6a9a 100644
--- a/lib/locomotive/liquid/tags/editable/content.rb
+++ b/lib/locomotive/liquid/tags/editable/content.rb
@@ -3,9 +3,9 @@ module Locomotive
module Tags
module Editable
class Content < ::Liquid::Tag
-
+
Syntax = /(#{::Liquid::Expression}+)?/
-
+
def initialize(tag_name, markup, tokens, context)
if markup =~ Syntax
@slug = $1
@@ -17,31 +17,31 @@ module Locomotive
super
end
-
+
def render(context)
page = context.registers[:page]
element = find_element(page)
-
+
if element.nil? && @options[:inherit] != false
while page.parent.present? && element.nil?
page = page.parent
element = find_element(page)
end
end
-
+
if element.present?
return element.content
else
raise ::Liquid::SyntaxError.new("Error in 'content' - Can't find editable element called `#{@slug}`")
end
end
-
+
def find_element(page)
page.editable_elements.where(:slug => @slug).first
end
-
+
end
-
+
::Liquid::Template.register_tag('content', Content)
end
end
diff --git a/lib/locomotive/mongoid/patches.rb b/lib/locomotive/mongoid/patches.rb
index 23b88516..d5ec0440 100644
--- a/lib/locomotive/mongoid/patches.rb
+++ b/lib/locomotive/mongoid/patches.rb
@@ -1,3 +1,91 @@
+# encoding: utf-8
+
require 'mongoid'
-## For now, no mongoid monkey patch is required, that is a good thing after all :-)
\ No newline at end of file
+# 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 skip()
+ # 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:
+ #
+ # criteria.limit(100)
+ # criteria.limit(100, { :contents => 5 })
+ # criteria.limit(:contents => 5)
+ #
+ # Returns: self
+ 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
\ No newline at end of file
diff --git a/locomotive_cms.gemspec b/locomotive_cms.gemspec
index 5db84620..fc92b0ad 100644
--- a/locomotive_cms.gemspec
+++ b/locomotive_cms.gemspec
@@ -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"
diff --git a/public/stylesheets/admin/menu.css b/public/stylesheets/admin/menu.css
index fba1dfe3..c67876c0 100644
--- a/public/stylesheets/admin/menu.css
+++ b/public/stylesheets/admin/menu.css
@@ -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;
diff --git a/public/stylesheets/sass/admin/menu.scss b/public/stylesheets/sass/admin/menu.scss
index 230bec14..aedbb53e 100644
--- a/public/stylesheets/sass/admin/menu.scss
+++ b/public/stylesheets/sass/admin/menu.scss
@@ -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;
}
}