common-content 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -20
- data/README.textile +55 -55
- data/Rakefile +29 -29
- data/app/assets/javascripts/application.js +15 -15
- data/app/assets/javascripts/contents.js.coffee +16 -16
- data/app/assets/javascripts/jquery-ui-1.8.21.custom.min.js +124 -124
- data/app/assets/stylesheets/bootstrap_and_overrides.css.less +29 -29
- data/app/assets/stylesheets/contents.css.less +6 -6
- data/app/assets/stylesheets/scaffolds.css.less +62 -62
- data/app/controllers/contents_controller.rb +99 -99
- data/app/helpers/contents_helper.rb +27 -34
- data/app/models/content.rb +71 -66
- data/app/models/textile.rb +15 -15
- data/app/views/contents/_array_form.html.erb +13 -13
- data/app/views/contents/_child_content_fields.html.erb +8 -14
- data/app/views/contents/_content.xml.builder +3 -3
- data/app/views/contents/_fields_edit.html.erb +7 -7
- data/app/views/contents/_fields_new.html.erb +12 -14
- data/app/views/contents/_navigation.html.erb +13 -0
- data/app/views/contents/_resource_fields.html.erb +23 -21
- data/app/views/contents/_seo_fields.html.erb +21 -21
- data/app/views/contents/_show_children.html.erb +10 -10
- data/app/views/contents/edit.html.erb +51 -44
- data/app/views/contents/index.html.erb +33 -34
- data/app/views/contents/index.xml.builder +4 -4
- data/app/views/contents/new.html.erb +13 -13
- data/app/views/contents/show.html.erb +25 -25
- data/app/views/layouts/contents.html.erb +46 -64
- data/config/routes.rb +9 -9
- data/lib/common-content.rb +4 -4
- data/lib/common-content/engine.rb +7 -7
- data/lib/common-content/version.rb +3 -3
- data/lib/tasks/common-content_tasks.rake +4 -4
- metadata +44 -73
data/app/models/content.rb
CHANGED
@@ -1,67 +1,72 @@
|
|
1
|
-
class Content
|
2
|
-
include Mongoid::Document
|
3
|
-
include Mongoid::Timestamps
|
4
|
-
|
5
|
-
field :slug, type: String
|
6
|
-
validates :slug, presence: true, uniqueness: true
|
7
|
-
key :slug
|
8
|
-
|
9
|
-
field :title, type: String
|
10
|
-
validates :title, presence: true
|
11
|
-
|
12
|
-
field :body, type: Textile # optional html block of text for this content
|
13
|
-
|
14
|
-
embeds_one :seo, class_name: 'Content::Seo' # optional SEO fields
|
15
|
-
accepts_nested_attributes_for :seo # mongoid BUG see http://stackoverflow.com/questions/9392315/mongoid-and-nested-form-for-embeds-one-document
|
16
|
-
|
17
|
-
embeds_many :resources, class_name: 'Content::Resource' # optional 1-n resources like images, videos, REST urls, etc
|
18
|
-
accepts_nested_attributes_for :resources # mongoid BUG see http://stackoverflow.com/questions/9392315/mongoid-and-nested-form-for-embeds-one-document
|
19
|
-
|
20
|
-
recursively_embeds_many # optionaal 1-n embedded child Content objects, the editable field controls if user can change
|
21
|
-
accepts_nested_attributes_for :child_contents # mongoid BUG see http://stackoverflow.com/questions/9392315/mongoid-and-nested-form-for-embeds-one-document
|
22
|
-
|
23
|
-
# embeds_one :constraint # the constraints of what fields are required, what child objects can be defined and how many, etc.
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
def
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
1
|
+
class Content
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
|
5
|
+
field :slug, type: String
|
6
|
+
validates :slug, presence: true, uniqueness: true
|
7
|
+
key :slug
|
8
|
+
|
9
|
+
field :title, type: String
|
10
|
+
validates :title, presence: true
|
11
|
+
|
12
|
+
field :body, type: Textile # optional html block of text for this content
|
13
|
+
|
14
|
+
embeds_one :seo, class_name: 'Content::Seo' # optional SEO fields
|
15
|
+
accepts_nested_attributes_for :seo # mongoid BUG see http://stackoverflow.com/questions/9392315/mongoid-and-nested-form-for-embeds-one-document
|
16
|
+
|
17
|
+
embeds_many :resources, class_name: 'Content::Resource' # optional 1-n resources like images, videos, REST urls, etc
|
18
|
+
accepts_nested_attributes_for :resources # mongoid BUG see http://stackoverflow.com/questions/9392315/mongoid-and-nested-form-for-embeds-one-document
|
19
|
+
|
20
|
+
recursively_embeds_many # optionaal 1-n embedded child Content objects, the editable field controls if user can change
|
21
|
+
accepts_nested_attributes_for :child_contents # mongoid BUG see http://stackoverflow.com/questions/9392315/mongoid-and-nested-form-for-embeds-one-document
|
22
|
+
|
23
|
+
# embeds_one :constraint # the constraints of what fields are required, what child objects can be defined and how many, etc.
|
24
|
+
before_save do
|
25
|
+
p "calling before_save @child_order = #{@child_order}"
|
26
|
+
return unless @child_order
|
27
|
+
order = @child_order.split(',')
|
28
|
+
order.each {|e| e.strip!}
|
29
|
+
self.child_contents = self.child_contents.sort_by {|kid| order.index(kid.id) or -1 }
|
30
|
+
end
|
31
|
+
|
32
|
+
def ancestry
|
33
|
+
parent_content ? parent_content.ancestry << id : [id]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_by_ancestry(ancestry = nil, id)
|
37
|
+
return self.find(id) unless ancestry
|
38
|
+
parent = Content.find(ancestry.shift)
|
39
|
+
while(parent_slug = ancestry.shift and parent_slug != id) do
|
40
|
+
parent = parent.child_contents.find(parent_slug)
|
41
|
+
end if parent
|
42
|
+
parent.child_contents.find(id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def child_order=(order)
|
46
|
+
@child_order = order
|
47
|
+
end
|
48
|
+
def child_order; end
|
49
|
+
|
50
|
+
def to_param
|
51
|
+
parent_content ? parent_content.to_param + '/' + id : id
|
52
|
+
end
|
53
|
+
|
54
|
+
class Resource
|
55
|
+
include Mongoid::Document
|
56
|
+
embedded_in :content
|
57
|
+
|
58
|
+
field :slug, type: String
|
59
|
+
field :uri, type: String # the URI of the entity we're linking to
|
60
|
+
field :content_type, type: String # mime type if there is one
|
61
|
+
end
|
62
|
+
|
63
|
+
class Seo
|
64
|
+
include Mongoid::Document
|
65
|
+
embedded_in :content
|
66
|
+
|
67
|
+
field :description, type: String
|
68
|
+
field :keywords, type: String
|
69
|
+
field :metatitle, type: String
|
70
|
+
# validates :description, :keywords, :metatitle, presence: true
|
71
|
+
end
|
67
72
|
end
|
data/app/models/textile.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
require 'RedCloth'
|
2
|
-
|
3
|
-
class Textile < RedCloth::TextileDoc
|
4
|
-
include Mongoid::Fields::Serializable
|
5
|
-
|
6
|
-
attr_accessor :max
|
7
|
-
|
8
|
-
def serialize(object)
|
9
|
-
object.to_s
|
10
|
-
end
|
11
|
-
def deserialize(object)
|
12
|
-
object = '' unless object
|
13
|
-
RedCloth.new(object)
|
14
|
-
end
|
15
|
-
|
1
|
+
require 'RedCloth'
|
2
|
+
|
3
|
+
class Textile < RedCloth::TextileDoc
|
4
|
+
include Mongoid::Fields::Serializable
|
5
|
+
|
6
|
+
attr_accessor :max
|
7
|
+
|
8
|
+
def serialize(object)
|
9
|
+
object.to_s
|
10
|
+
end
|
11
|
+
def deserialize(object)
|
12
|
+
object = '' unless object
|
13
|
+
RedCloth.new(object)
|
14
|
+
end
|
15
|
+
|
16
16
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
<% f.object.send(fk).each_with_index do |ar, idx| %>
|
2
|
-
<div class="control-group">
|
3
|
-
<%= f.fields_for fk do |ar_form| %>
|
4
|
-
<div class="controls">
|
5
|
-
<!-- do some stuff to see if this type has a specific view partial -->
|
6
|
-
<% if File.file?(File.expand_path("_#{ar.type.to_s.downcase}_form.html.erb", File.dirname(__FILE__))) %>
|
7
|
-
<%= render :partial => "#{ar.type.to_s.downcase}_form", :locals => {f: f, fk: fk} %>
|
8
|
-
<% else %>
|
9
|
-
<%= ar_form.text_field "", :class => 'text_field', :value => ar %>
|
10
|
-
<% end %>
|
11
|
-
</div>
|
12
|
-
<% end %>
|
13
|
-
</div>
|
1
|
+
<% f.object.send(fk).each_with_index do |ar, idx| %>
|
2
|
+
<div class="control-group">
|
3
|
+
<%= f.fields_for fk do |ar_form| %>
|
4
|
+
<div class="controls">
|
5
|
+
<!-- do some stuff to see if this type has a specific view partial -->
|
6
|
+
<% if File.file?(File.expand_path("_#{ar.type.to_s.downcase}_form.html.erb", File.dirname(__FILE__))) %>
|
7
|
+
<%= render :partial => "#{ar.type.to_s.downcase}_form", :locals => {f: f, fk: fk} %>
|
8
|
+
<% else %>
|
9
|
+
<%= ar_form.text_field "", :class => 'text_field', :value => ar %>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
14
|
<% end %>
|
@@ -1,14 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
<%= f.label :title, :class => 'control-label' %>
|
10
|
-
<div class="controls">
|
11
|
-
<%= f.text_field :title, :class => 'text_field' %>
|
12
|
-
</div>
|
13
|
-
</div>
|
14
|
-
</fieldset>
|
1
|
+
<% child_index = (child_index or f.object.id) %>
|
2
|
+
<div id='<%= child_index %>' class="embedded-child">
|
3
|
+
<%= link_to f.object.title, f.object %>
|
4
|
+
<fieldset>
|
5
|
+
<%= render :partial => 'fields_new', :locals => {f: f} %>
|
6
|
+
<%= render :partial => 'fields_edit', :locals => {f: f} %>
|
7
|
+
</fieldset>
|
8
|
+
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
xml.content do
|
2
|
-
xml.name(content.slug)
|
3
|
-
xml.link('rel' => 'self', 'uri' => content_path(content))
|
1
|
+
xml.content do
|
2
|
+
xml.name(content.slug)
|
3
|
+
xml.link('rel' => 'self', 'uri' => content_path(content))
|
4
4
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
<div class="control-group">
|
2
|
-
<%= f.label :body, :class => 'control-label' %>
|
3
|
-
<div class="controls">
|
4
|
-
<%= f.text_area :body, :class => 'text_area' %>
|
5
|
-
</div>
|
6
|
-
</div>
|
7
|
-
|
1
|
+
<div class="control-group">
|
2
|
+
<%= f.label :body, :class => 'control-label' %>
|
3
|
+
<div class="controls">
|
4
|
+
<%= f.text_area :body, :class => 'text_area', rows: '3' %>
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
|
@@ -1,14 +1,12 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
</div>
|
14
|
-
</fieldset>
|
1
|
+
<div class="control-group">
|
2
|
+
<%= f.label :slug, :class => 'control-label' %>
|
3
|
+
<div class="controls">
|
4
|
+
<%= f.text_field :slug, :class => 'text_field', disabled: !f.object.new? %>
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
<div class="control-group">
|
8
|
+
<%= f.label 'title', :class => 'control-label' %>
|
9
|
+
<div class="controls">
|
10
|
+
<%= f.text_field :title, :class => 'text_field' %>
|
11
|
+
</div>
|
12
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
<div class="navbar navbar-fixed-top">
|
3
|
+
<div class="container-fluid">
|
4
|
+
<div class="container-fluid nav-collapse">
|
5
|
+
<ul class="breadcrumb">
|
6
|
+
<li><%= link_to "Contents", "/contents" %></li>
|
7
|
+
<% @content.try(:ancestry).try(:each) do |crumb| %>
|
8
|
+
<li>/ <%= link_to crumb %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div><!--/.nav-collapse -->
|
12
|
+
</div>
|
13
|
+
</div>
|
@@ -1,21 +1,23 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
<div id='<%= f.object.id %>'>
|
2
|
+
<fieldset>
|
3
|
+
<div class="control-group">
|
4
|
+
<%= f.label :slug, :class => 'control-label' %>
|
5
|
+
<div class="controls">
|
6
|
+
<%= f.text_field :slug, :class => 'text_field' %>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
<div class="control-group">
|
10
|
+
<%= f.label :uri, :class => 'control-label' %>
|
11
|
+
<div class="controls">
|
12
|
+
<%= f.text_field :uri, :class => 'text_field' %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<div class="control-group">
|
16
|
+
<%= f.label :type, :class => 'control-label' %>
|
17
|
+
<div class="controls">
|
18
|
+
<%= f.text_field :content_type, :class => 'text_field' %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
<hr/>
|
22
|
+
</fieldset>
|
23
|
+
</div>
|
@@ -1,22 +1,22 @@
|
|
1
|
-
<fieldset>
|
2
|
-
<h5>SEO</h5>
|
3
|
-
<div class="control-group">
|
4
|
-
<%= f.label :title, :class => 'control-label' %>
|
5
|
-
<div class="controls">
|
6
|
-
<%= f.text_field :metatitle, :class => 'text_field' %>
|
7
|
-
</div>
|
8
|
-
</div>
|
9
|
-
<div class="control-group">
|
10
|
-
<%= f.label :description, :class => 'control-label' %>
|
11
|
-
<div class="controls">
|
12
|
-
<%= f.text_area :description, :class => 'text_area meta_description', rows: '3' %>
|
13
|
-
</div>
|
14
|
-
</div>
|
15
|
-
<div class="control-group">
|
16
|
-
<%= f.label :keywords, :class => 'control-label' %>
|
17
|
-
<div class="controls">
|
18
|
-
<%= f.text_field :keywords, :class => 'text_field' %>
|
19
|
-
</div>
|
20
|
-
</div>
|
21
|
-
<hr/>
|
1
|
+
<fieldset>
|
2
|
+
<h5>SEO</h5>
|
3
|
+
<div class="control-group">
|
4
|
+
<%= f.label :title, :class => 'control-label' %>
|
5
|
+
<div class="controls">
|
6
|
+
<%= f.text_field :metatitle, :class => 'text_field' %>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
<div class="control-group">
|
10
|
+
<%= f.label :description, :class => 'control-label' %>
|
11
|
+
<div class="controls">
|
12
|
+
<%= f.text_area :description, :class => 'text_area meta_description', rows: '3' %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<div class="control-group">
|
16
|
+
<%= f.label :keywords, :class => 'control-label' %>
|
17
|
+
<div class="controls">
|
18
|
+
<%= f.text_field :keywords, :class => 'text_field' %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
<hr/>
|
22
22
|
</fieldset>
|
@@ -1,10 +1,10 @@
|
|
1
|
-
<% # http://stackoverflow.com/questions/187073/jquery-sortables %>
|
2
|
-
<div class="">
|
3
|
-
<!-- <input type='hidden' name='content[child_order]' id='child_order' /> -->
|
4
|
-
<div id="children">
|
5
|
-
<% show_children.try :each do |child| %>
|
6
|
-
<%= content_tag :div, id: child.id do %>
|
7
|
-
<p><%= link_to child.title, contents_path + '/' + child.ancestry.join('/') + '/edit' %></p>
|
8
|
-
<% end; end -%>
|
9
|
-
</div>
|
10
|
-
</div>
|
1
|
+
<% # http://stackoverflow.com/questions/187073/jquery-sortables %>
|
2
|
+
<div class="">
|
3
|
+
<!-- <input type='hidden' name='content[child_order]' id='child_order' /> -->
|
4
|
+
<div id="children">
|
5
|
+
<% show_children.try :each do |child| %>
|
6
|
+
<%= content_tag :div, id: child.id do %>
|
7
|
+
<p><%= link_to child.title, contents_path + '/' + child.ancestry.join('/') + '/edit' %></p>
|
8
|
+
<% end; end -%>
|
9
|
+
</div>
|
10
|
+
</div>
|
@@ -1,44 +1,51 @@
|
|
1
|
-
<%- model_class = @content.class -%>
|
2
|
-
<div class="page-header">
|
3
|
-
<h3><%=t '.title', :default => t('helpers.titles.define', :model => model_class.model_name.human,
|
4
|
-
:default => "Edit #{@content.slug or model_class.model_name.human}") %></h3>
|
5
|
-
</div>
|
6
|
-
<%= form_for @content, :html => { :class => 'form-horizontal' } do |f| %>
|
7
|
-
<% if @content.errors.any? %>
|
8
|
-
<div class="errors">
|
9
|
-
<h3>ERROR!</h3>
|
10
|
-
<ul>
|
11
|
-
<% @content.errors.full_messages.each do |msg| %>
|
12
|
-
<%= content_tag :li, msg %>
|
13
|
-
<% end %>
|
14
|
-
</ul>
|
15
|
-
</div>
|
16
|
-
<% end %>
|
17
|
-
<%= render :partial => 'fields_new', :locals => {f: f} %>
|
18
|
-
<%= render :partial => 'fields_edit', :locals => {f: f} %>
|
19
|
-
<hr/>
|
20
|
-
<%= link_to_add_fields "+ seo", f, :seo unless @content.seo %>
|
21
|
-
<%= f.fields_for :seo do |seo| %>
|
22
|
-
<%= render :partial => 'seo_fields', :locals => {f: seo} %>
|
23
|
-
<% end %>
|
24
|
-
<h4>Resources</h4>
|
25
|
-
<%= link_to_add_fields "Add Resource", f, :resources %>
|
26
|
-
|
27
|
-
<%= f.fields_for :resources do |res| %>
|
28
|
-
<%= render :partial => 'resource_fields', :locals => {f: res} %>
|
29
|
-
<% end %>
|
30
|
-
|
31
|
-
|
32
|
-
<%=
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
1
|
+
<%- model_class = @content.class; @ancestry = @content.ancestry -%>
|
2
|
+
<div class="page-header">
|
3
|
+
<h3><%=t '.title', :default => t('helpers.titles.define', :model => model_class.model_name.human,
|
4
|
+
:default => "Edit #{@content.slug or model_class.model_name.human}") %></h3>
|
5
|
+
</div>
|
6
|
+
<%= form_for @content, :html => { :class => 'form-horizontal' } do |f| %>
|
7
|
+
<% if @content.errors.any? %>
|
8
|
+
<div class="errors">
|
9
|
+
<h3>ERROR!</h3>
|
10
|
+
<ul>
|
11
|
+
<% @content.errors.full_messages.each do |msg| %>
|
12
|
+
<%= content_tag :li, msg %>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
17
|
+
<%= render :partial => 'fields_new', :locals => {f: f} %>
|
18
|
+
<%= render :partial => 'fields_edit', :locals => {f: f} %>
|
19
|
+
<hr/>
|
20
|
+
<%= link_to_add_fields "+ seo", f, :seo unless @content.seo %>
|
21
|
+
<%= f.fields_for :seo do |seo| %>
|
22
|
+
<%= render :partial => 'seo_fields', :locals => {f: seo} %>
|
23
|
+
<% end %>
|
24
|
+
<h4>Resources</h4>
|
25
|
+
<%= link_to_add_fields "Add Resource", f, :resources, '#resources' %>
|
26
|
+
<div id="resources">
|
27
|
+
<%= f.fields_for :resources do |res| %>
|
28
|
+
<%= render :partial => 'resource_fields', :locals => {f: res} %>
|
29
|
+
<% end %>
|
30
|
+
</div>
|
31
|
+
<h4>Children</h4>
|
32
|
+
<%= f.hidden_field :child_order %>
|
33
|
+
<%= link_to_add_fields "Add Child", f, :child_contents, '#children' %>
|
34
|
+
<div id="children">
|
35
|
+
<%= f.fields_for :child_contents do |child| %>
|
36
|
+
<%= render :partial => 'child_content_fields', :locals => {f: child} %>
|
37
|
+
<% end %>
|
38
|
+
</div>
|
39
|
+
|
40
|
+
<div class="form-actions">
|
41
|
+
<%= f.submit nil, :class => 'btn btn-primary' %>
|
42
|
+
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
|
43
|
+
contents_path, :class => 'btn' %>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<% end %>
|
47
|
+
|
48
|
+
<% content_for :breadcrumb do %>
|
49
|
+
<%= content_tag :anchor, @content.ancestry %>
|
50
|
+
<% end %>
|
51
|
+
|