browsercms 3.3.2 → 3.3.3
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/app/controllers/cms/content_block_controller.rb +2 -2
- data/app/controllers/cms/content_controller.rb +1 -1
- data/app/controllers/cms/section_nodes_controller.rb +6 -1
- data/app/controllers/cms/sections_controller.rb +1 -1
- data/app/helpers/cms/application_helper.rb +1 -1
- data/app/helpers/cms/content_block_helper.rb +27 -0
- data/app/helpers/cms/section_nodes_helper.rb +43 -5
- data/app/models/abstract_file_block.rb +17 -2
- data/app/models/attachment.rb +16 -34
- data/app/models/file_block.rb +0 -12
- data/app/models/image_block.rb +0 -12
- data/app/models/link.rb +4 -21
- data/app/models/page.rb +36 -35
- data/app/models/section.rb +82 -42
- data/app/models/section_node.rb +41 -24
- data/app/views/cms/blocks/index.html.erb +4 -4
- data/app/views/cms/file_blocks/_form.html.erb +1 -1
- data/app/views/cms/image_blocks/_form.html.erb +1 -1
- data/app/views/cms/section_nodes/_link.html.erb +6 -3
- data/app/views/cms/section_nodes/_node.html.erb +11 -2
- data/app/views/cms/section_nodes/_page.html.erb +13 -7
- data/app/views/cms/section_nodes/_section.html.erb +24 -8
- data/app/views/cms/section_nodes/index.html.erb +18 -6
- data/app/views/cms/shared/_pagination.html.erb +4 -4
- data/app/views/portlets/reset_password/render.html.erb +0 -2
- data/browsercms.gemspec +1 -4
- data/db/migrate/20100117144039_browsercms315.rb +94 -0
- data/lib/acts_as_list.rb +1 -1
- data/lib/browsercms.rb +3 -1
- data/lib/cms/addressable.rb +83 -0
- data/lib/cms/behaviors/attaching.rb +42 -24
- data/lib/cms/behaviors/connecting.rb +2 -1
- data/lib/cms/behaviors/publishing.rb +12 -3
- data/lib/cms/behaviors/versioning.rb +43 -24
- data/lib/cms/content_rendering_support.rb +3 -3
- data/lib/cms/error_pages.rb +8 -0
- data/lib/cms/version.rb +2 -2
- data/lib/generators/browser_cms/cms/cms_generator.rb +1 -0
- data/lib/generators/cms/upgrade_module/templates/GPL.txt +1 -1
- data/lib/tasks/data.rake +43 -0
- metadata +27 -8
- data/app/views/cms/section_nodes/_section_node.html.erb +0 -10
data/app/models/section_node.rb
CHANGED
@@ -1,10 +1,33 @@
|
|
1
|
+
require 'ancestry'
|
2
|
+
|
1
3
|
class SectionNode < ActiveRecord::Base
|
2
|
-
|
3
|
-
|
4
|
+
has_ancestry
|
5
|
+
|
6
|
+
# This is the parent section for this node
|
7
|
+
# For backwards compatiblity
|
8
|
+
def parent_section
|
9
|
+
self.parent ? self.parent.node : nil
|
10
|
+
end
|
11
|
+
|
12
|
+
alias :section :parent_section
|
4
13
|
|
5
|
-
|
14
|
+
# For backwards compatiblity
|
15
|
+
def section=(new_section)
|
16
|
+
self.parent = new_section.node
|
17
|
+
end
|
18
|
+
|
19
|
+
# The item this node links to
|
20
|
+
belongs_to :node, :polymorphic => :true, :inverse_of => :section_node
|
21
|
+
|
22
|
+
acts_as_list
|
23
|
+
# For acts_as_list. Specifies that position should be unique within a section.
|
24
|
+
def scope_condition
|
25
|
+
ancestry ? "ancestry = '#{ancestry}'" : 'ancestry IS NULL'
|
26
|
+
end
|
6
27
|
|
7
28
|
scope :of_type, lambda{|types| {:conditions => ["section_nodes.node_type IN (?)", types]}}
|
29
|
+
scope :in_order, :order => "position asc"
|
30
|
+
scope :fetch_nodes, :include => :node
|
8
31
|
|
9
32
|
def visible?
|
10
33
|
return false unless node
|
@@ -27,27 +50,29 @@ class SectionNode < ActiveRecord::Base
|
|
27
50
|
def page?
|
28
51
|
node_type == 'Page'
|
29
52
|
end
|
30
|
-
|
31
|
-
|
53
|
+
|
54
|
+
# @param [Section] section
|
55
|
+
# @param [Integer] position
|
56
|
+
def move_to(section, position)
|
32
57
|
#logger.info "Moving Section Node ##{id} to Section ##{sec.id} Position #{pos}"
|
33
58
|
transaction do
|
34
|
-
if
|
59
|
+
if self.parent != section.node
|
35
60
|
remove_from_list
|
36
|
-
self.
|
61
|
+
self.parent = section.node
|
37
62
|
save
|
38
63
|
end
|
39
64
|
|
40
|
-
if
|
41
|
-
|
65
|
+
if position < 0
|
66
|
+
position = 0
|
42
67
|
else
|
43
68
|
#This helps prevent the position from getting out of whack
|
44
69
|
#If you pass in a really high number for position,
|
45
70
|
#this just corrects it to the right number
|
46
|
-
node_count = SectionNode.count(:conditions => {:
|
47
|
-
|
71
|
+
node_count = SectionNode.count(:conditions => {:ancestry => ancestry})
|
72
|
+
position = node_count if position > node_count
|
48
73
|
end
|
49
74
|
|
50
|
-
insert_at_position(
|
75
|
+
insert_at_position(position)
|
51
76
|
end
|
52
77
|
end
|
53
78
|
|
@@ -77,17 +102,9 @@ class SectionNode < ActiveRecord::Base
|
|
77
102
|
#1.0/0 == Infinity
|
78
103
|
move_to(sec, 1.0/0)
|
79
104
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
ancestors << sn.section
|
85
|
-
if sn.section && !sn.section.root?
|
86
|
-
fn.call(sn.section.node)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
fn.call(self)
|
90
|
-
ancestors.reverse
|
105
|
+
|
106
|
+
|
107
|
+
def ancestry_path
|
108
|
+
path_ids.join "/"
|
91
109
|
end
|
92
|
-
|
93
110
|
end
|
@@ -50,7 +50,6 @@
|
|
50
50
|
<% page_title "Content Library / List #{content_type.display_name_plural}" %>
|
51
51
|
<% @toolbar_title = "List #{content_type.display_name_plural}" %>
|
52
52
|
<%= render :partial => 'cms/blocks/toolbar' %>
|
53
|
-
|
54
53
|
<div class="roundedcorners">
|
55
54
|
<table id="blocks" class="data">
|
56
55
|
<thead>
|
@@ -90,8 +89,9 @@
|
|
90
89
|
col_ct += 1 if content_type.model_class.publishable? %>
|
91
90
|
<% @blocks.each do |b| %>
|
92
91
|
<% block = b.class.versioned? ? b.as_of_draft_version : b %>
|
93
|
-
|
94
|
-
|
92
|
+
|
93
|
+
<%= block_row_tag(block) %>
|
94
|
+
<td class="first"></td>
|
95
95
|
<% content_type.columns_for_index.each_with_index do |column, i| %>
|
96
96
|
<td class="<%= column[:label].gsub(' ', '').underscore %>">
|
97
97
|
<div<%= ' class="dividers"' if (i + 3 < col_ct) %>>
|
@@ -105,7 +105,7 @@
|
|
105
105
|
</td>
|
106
106
|
<% end %>
|
107
107
|
<% if content_type.model_class.respond_to?(:updated_at) %><td class="updated"><div class="dividers"><%= block.updated_at.to_s(:date) %></div></td><% end %>
|
108
|
-
<% if content_type.model_class.connectable? %><td class="used"><div class="dividers"><%= block.connected_pages.
|
108
|
+
<% if content_type.model_class.connectable? %><td class="used"><div class="dividers"><%= block.connected_pages.size %></div></td><% end %>
|
109
109
|
<% if content_type.model_class.publishable? %><td class="block_status"><%= status_icon(block.status) %> <div><%= block.status %></div></td><% end %>
|
110
110
|
<td class="last"></td>
|
111
111
|
</tr>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
root.full_path = root.name
|
4
4
|
@sections = []
|
5
5
|
@sections << root
|
6
|
-
@sections += root.
|
6
|
+
@sections += root.master_section_list
|
7
7
|
@sections.each {|s| s.full_path = "/" + s.full_path unless s == root }
|
8
8
|
@block.attachment_file_path = @block.attachment.file_path if @block.attachment_file_path.blank? && !@block.new_record?
|
9
9
|
%>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
root.full_path = root.name
|
4
4
|
@sections = []
|
5
5
|
@sections << root
|
6
|
-
@sections += root.
|
6
|
+
@sections += root.master_section_list
|
7
7
|
@sections.each {|s| s.full_path = "/" + s.full_path unless s == root }
|
8
8
|
@block.attachment_file_path = @block.attachment.file_path if @block.attachment_file_path.blank? && !@block.new_record?
|
9
9
|
%>
|
@@ -1,11 +1,14 @@
|
|
1
|
-
|
1
|
+
<% first_level = in_first_level?(node)
|
2
|
+
%>
|
3
|
+
<%= sitemap_ul_tag(node) %>
|
2
4
|
<li>
|
3
5
|
<%= render :partial => "node", :locals => {
|
4
6
|
:node => node,
|
5
7
|
:node_type => "link",
|
6
|
-
:icon => action_icon(
|
8
|
+
:icon => action_icon(first_level ? :root_link : :link),
|
7
9
|
:published_status_icon => status_icon(node.status),
|
8
|
-
:published_status_label => node.published? ? "Published" : "Draft"
|
10
|
+
:published_status_label => node.published? ? "Published" : "Draft",
|
11
|
+
:parent => parent
|
9
12
|
} %>
|
10
13
|
</li>
|
11
14
|
</ul>
|
@@ -4,13 +4,22 @@
|
|
4
4
|
published_status_icon = defined?(published_status_icon) ? published_status_icon : nil
|
5
5
|
published_status_label = defined?(published_status_label) ? published_status_label : nil
|
6
6
|
|
7
|
+
editable_class = ""
|
8
|
+
case node_type
|
9
|
+
when "section"
|
10
|
+
editable_class = "non-editable" unless @modifiable_sections.include?(node)
|
11
|
+
else
|
12
|
+
editable_class = "non-editable" unless defined?(parent) && @modifiable_sections.include?(parent)
|
13
|
+
end
|
14
|
+
|
15
|
+
node_type_class = node_type == "section" && node.root? ? 'root' : ''
|
7
16
|
%>
|
8
17
|
<div class="roundedcorners">
|
9
18
|
<table class="section_node <%= node_type %> <%= "movable" if current_user.able_to?(:publish_content) %>" width="100%" cellspacing="0" cellpadding="0">
|
10
19
|
<tr><td colspan="4" class="drop-before"></td></tr>
|
11
20
|
<tr<%= ' class="doubled"' if access_icon && hidden %>>
|
12
|
-
<td id="<%= node_type %>_<%= node.id %>" class="<%=
|
13
|
-
<%=
|
21
|
+
<td id="<%= node_type %>_<%= node.id %>" class="<%= node_type_class %> <%= node_type %> node <%= editable_class %>">
|
22
|
+
<%= icon.html_safe %>
|
14
23
|
<div><%= h(node.name) %></div>
|
15
24
|
</td>
|
16
25
|
<td class="sitemap_hidden divided">
|
@@ -1,14 +1,20 @@
|
|
1
|
-
<%
|
2
|
-
|
1
|
+
<%
|
2
|
+
page = node
|
3
|
+
status_icon = page.archived? ? :archived : page.status
|
4
|
+
first_level = in_first_level?(node)
|
5
|
+
|
6
|
+
%>
|
7
|
+
<%= sitemap_ul_tag(node) %>
|
3
8
|
<li>
|
4
9
|
<%= render :partial => "node", :locals => {
|
5
10
|
:node => node,
|
6
11
|
:node_type => "page",
|
7
|
-
:icon => action_icon(
|
8
|
-
:hidden =>
|
9
|
-
:access_icon => status_icon(
|
10
|
-
:published_status_icon => status_icon(
|
11
|
-
:published_status_label =>
|
12
|
+
:icon => action_icon(first_level ? :root_page : :page),
|
13
|
+
:hidden => page.hidden?,
|
14
|
+
:access_icon => status_icon(access_icon),
|
15
|
+
:published_status_icon => status_icon(status_icon),
|
16
|
+
:published_status_label => status_icon.to_s.titleize,
|
17
|
+
:parent => parent
|
12
18
|
} %>
|
13
19
|
</li>
|
14
20
|
</ul>
|
@@ -1,12 +1,28 @@
|
|
1
|
-
|
1
|
+
<%
|
2
|
+
children = child_hash[key].keys
|
3
|
+
section_node = key
|
4
|
+
access_status = access_status(node, @public_sections)
|
5
|
+
first_level = in_first_level?(node)
|
6
|
+
%>
|
7
|
+
<%= sitemap_ul_tag(node) %>
|
2
8
|
<li>
|
3
9
|
<%= render :partial => "node", :locals => {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
:node => node,
|
11
|
+
:node_type => "section",
|
12
|
+
:icon => "#{section_icons(section_node, children)} #{action_icon(first_level ? :root_folder : :folder, :class => "folder")}",
|
13
|
+
:hidden => node.hidden?,
|
14
|
+
:access_icon => status_icon(access_status),
|
15
|
+
:parent => parent
|
16
|
+
} %>
|
17
|
+
<% children.each do |child_section_node| %>
|
18
|
+
<%= render :partial => child_section_node.node.partial_for,
|
19
|
+
:locals => {:access_icon => access_status,
|
20
|
+
:node => child_section_node.node,
|
21
|
+
:parent => node,
|
22
|
+
:child_hash => child_hash[key],
|
23
|
+
:key => child_section_node
|
24
|
+
} %>
|
25
|
+
<% end %>
|
26
|
+
|
11
27
|
</li>
|
12
28
|
</ul>
|
@@ -20,12 +20,24 @@
|
|
20
20
|
<ul id="root_<%= @section.id %>" class="root" style="padding-left: 0">
|
21
21
|
<li>
|
22
22
|
<%= render :partial => "node", :locals => {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
:node => @section,
|
24
|
+
:node_type => "section",
|
25
|
+
:icon => action_icon(:home),
|
26
|
+
:display => true
|
27
|
+
} %>
|
28
28
|
</li>
|
29
29
|
</ul>
|
30
|
-
|
30
|
+
<%
|
31
|
+
access_status = access_status(@section, @public_sections)
|
32
|
+
@sitemap[@root_section_node].keys.each do |child_section_node| %>
|
33
|
+
<%= render :partial => child_section_node.node.partial_for,
|
34
|
+
:locals => {:access_icon => access_status,
|
35
|
+
:node => child_section_node.node,
|
36
|
+
:parent => @section,
|
37
|
+
:child_hash => @sitemap[@root_section_node],
|
38
|
+
:key => child_section_node
|
39
|
+
}
|
40
|
+
%>
|
41
|
+
<% end %>
|
31
42
|
</div>
|
43
|
+
|
@@ -8,8 +8,8 @@
|
|
8
8
|
<%= collection.total_entries %>
|
9
9
|
</div>
|
10
10
|
<div class="links">
|
11
|
-
<%= link_to " ", first_page_path, :id => "first_page_link" %>
|
12
|
-
<%= link_to " ", previous_page_path, :id => "previous_page_link" %>
|
11
|
+
<%= link_to " ".html_safe, first_page_path, :id => "first_page_link" %>
|
12
|
+
<%= link_to " ".html_safe, previous_page_path, :id => "previous_page_link" %>
|
13
13
|
<span>
|
14
14
|
<% url = URI.parse(current_page_path) %>
|
15
15
|
<%= form_tag url.path, :method => :get, :class => "current_page" do %>
|
@@ -24,8 +24,8 @@
|
|
24
24
|
</strong>
|
25
25
|
<% end %>
|
26
26
|
</span>
|
27
|
-
<%= link_to " ", next_page_path, :id => "next_page_link" %>
|
28
|
-
<%= link_to " ", last_page_path, :id => "last_page_link" %>
|
27
|
+
<%= link_to " ".html_safe, next_page_path, :id => "next_page_link" %>
|
28
|
+
<%= link_to " ".html_safe, last_page_path, :id => "last_page_link" %>
|
29
29
|
</div>
|
30
30
|
<br clear="all"/>
|
31
31
|
</div>
|
data/browsercms.gemspec
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# This file is now managed directly, rather than generated by Jeweler.
|
2
|
-
#
|
3
1
|
require File.dirname(__FILE__) + "/lib/cms/version.rb"
|
4
2
|
|
5
3
|
Gem::Specification.new do |s|
|
@@ -7,9 +5,7 @@ Gem::Specification.new do |s|
|
|
7
5
|
s.name = %q{browsercms}
|
8
6
|
s.version = Cms::VERSION
|
9
7
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
8
|
s.authors = ["BrowserMedia"]
|
12
|
-
s.date = %q{2011-03-15}
|
13
9
|
s.summary = %q{BrowserCMS is a a general purpose, open source Web Content Management System (CMS), written using Ruby on Rails.}
|
14
10
|
s.description = %q{Web Content Management in Rails.}
|
15
11
|
s.email = %q{github@browsermedia.com}
|
@@ -42,6 +38,7 @@ Gem::Specification.new do |s|
|
|
42
38
|
s.files -= Dir['test/dummy/*']
|
43
39
|
|
44
40
|
s.add_dependency('rails', "~> 3.0.7")
|
41
|
+
s.add_dependency "ancestry", "~> 1.2.4"
|
45
42
|
|
46
43
|
# Required only for bcms-upgrade
|
47
44
|
s.add_dependency('term-ansicolor')
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class Browsercms315 < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
generate_ancestry_from_section_id
|
4
|
+
update_latest_version_cache
|
5
|
+
|
6
|
+
INDEXES.each do |index|
|
7
|
+
add_index *index
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
# This migration is not reversible since it removes the original section_id column.
|
13
|
+
end
|
14
|
+
|
15
|
+
# Add some very commonly used indexes to improve the site performance as the # of pages/content grows (i.e. several thousand pages)
|
16
|
+
INDEXES = [
|
17
|
+
[:pages, :deleted],
|
18
|
+
[:pages, :path],
|
19
|
+
[:pages, :version],
|
20
|
+
[:page_versions, :page_id],
|
21
|
+
[:groups, :code],
|
22
|
+
[:groups, :group_type_id],
|
23
|
+
[:group_types, :cms_access],
|
24
|
+
[:group_sections, :section_id],
|
25
|
+
[:group_sections, :group_id],
|
26
|
+
[:users, :expires_at],
|
27
|
+
[:user_group_memberships, :group_id],
|
28
|
+
[:user_group_memberships, :user_id],
|
29
|
+
[:group_permissions, :group_id],
|
30
|
+
[:group_permissions, :permission_id],
|
31
|
+
[:group_permissions, [:group_id, :permission_id]],
|
32
|
+
[:section_nodes, :node_type],
|
33
|
+
[:section_nodes, :ancestry],
|
34
|
+
[:connectors, :page_id],
|
35
|
+
[:connectors, :page_version],
|
36
|
+
[:html_blocks, :deleted],
|
37
|
+
[:html_block_versions, :html_block_id],
|
38
|
+
[:html_block_versions, :version],
|
39
|
+
[:portlet_attributes, :portlet_id],
|
40
|
+
[:portlets, :name],
|
41
|
+
[:sections, :path],
|
42
|
+
[:redirects, :from_path],
|
43
|
+
[:connectors, :connectable_version],
|
44
|
+
[:connectors, :connectable_type],
|
45
|
+
[:content_types, :content_type_group_id],
|
46
|
+
[:content_types, :name],
|
47
|
+
[:file_block_versions, :file_block_id],
|
48
|
+
[:file_block_versions, :version],
|
49
|
+
[:file_blocks, :deleted],
|
50
|
+
[:file_blocks, :type],
|
51
|
+
[:attachment_versions, :attachment_id],
|
52
|
+
[:tasks, :page_id],
|
53
|
+
[:tasks, :completed_at],
|
54
|
+
[:tasks, :assigned_to_id],
|
55
|
+
]
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# v3.1.5 uses Ancestry to manage the parent child relationship between sections and their children.
|
60
|
+
# This converts the data from the old section_id to use the ancestry column.
|
61
|
+
def self.generate_ancestry_from_section_id
|
62
|
+
add_column :section_nodes, :ancestry, :string
|
63
|
+
add_column :section_nodes, :temp_parent_id, :integer
|
64
|
+
|
65
|
+
SectionNode.reset_column_information
|
66
|
+
root_section = Section.root.first
|
67
|
+
SectionNode.create!(:node => root_section) if root_section
|
68
|
+
|
69
|
+
all_nodes_but_root = SectionNode.find(:all, :conditions=>["section_id IS NOT NULL"])
|
70
|
+
all_nodes_but_root.each do |sn|
|
71
|
+
parent_node = SectionNode.find(:first, :conditions => ["node_id = ? and node_type = 'Section'", sn.section_id])
|
72
|
+
sn.temp_parent_id = parent_node.id
|
73
|
+
sn.save!
|
74
|
+
end
|
75
|
+
rename_column :section_nodes, :temp_parent_id, :parent_id # Ancestry works off the 'parent_id' column.
|
76
|
+
|
77
|
+
SectionNode.build_ancestry_from_parent_ids!
|
78
|
+
remove_column :section_nodes, :section_id
|
79
|
+
remove_column :section_nodes, :parent_id
|
80
|
+
SectionNode.reset_column_information
|
81
|
+
end
|
82
|
+
|
83
|
+
# Adds a 'latest_version' pointer to pages and links. Greatly reduces the number of queries the sitemap requires to determine if pages are in draft/published mode
|
84
|
+
def self.update_latest_version_cache
|
85
|
+
add_column :pages, :latest_version, :integer
|
86
|
+
add_column :links, :latest_version, :integer
|
87
|
+
Page.all.each do |p|
|
88
|
+
p.update_latest_version
|
89
|
+
end
|
90
|
+
Link.all.each do |link|
|
91
|
+
link.update_latest_version
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/acts_as_list.rb
CHANGED
@@ -7,7 +7,7 @@ module ActsAsList
|
|
7
7
|
# The class that has this specified needs to have a +position+ column defined as an integer on
|
8
8
|
# the mapped database table.
|
9
9
|
#
|
10
|
-
#
|
10
|
+
# To Do list example:
|
11
11
|
#
|
12
12
|
# class TodoList < ActiveRecord::Base
|
13
13
|
# has_many :todo_items, :order => "position"
|