alchemy_cms 2.0.rc6 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -1
- data/LICENSE +24 -619
- data/README.md +38 -36
- data/alchemy_cms.gemspec +1 -1
- data/app/controllers/admin/elements_controller.rb +3 -2
- data/app/controllers/admin/pages_controller.rb +20 -14
- data/app/controllers/admin/trash_controller.rb +4 -0
- data/app/controllers/pages_controller.rb +27 -16
- data/app/helpers/admin/elements_helper.rb +55 -0
- data/app/helpers/alchemy_helper.rb +0 -45
- data/app/helpers/elements_helper.rb +8 -1
- data/app/helpers/pages_helper.rb +0 -10
- data/app/models/element.rb +39 -5
- data/app/models/page.rb +27 -7
- data/app/sweepers/pages_sweeper.rb +0 -9
- data/app/views/admin/pages/update.js.erb +15 -1
- data/app/views/admin/partials/_upload_form.html.erb +2 -2
- data/app/views/elements/_contactform_view.html.erb +10 -23
- data/app/views/elements/_searchresult_view.html.erb +47 -40
- data/app/views/essences/_essence_html_view.html.erb +1 -1
- data/app/views/pages/show.rss.builder +20 -25
- data/assets/javascripts/alchemy.js +2 -2
- data/assets/stylesheets/elements.css +1 -1
- data/assets/stylesheets/standard_set.css +84 -14
- data/config/alchemy/elements.yml +2 -0
- data/config/alchemy/page_layouts.yml +1 -0
- data/config/locales/de.yml +5 -5
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/plugin/templates/config.yml +3 -3
- data/spec/controllers/admin/trash_controller_spec.rb +22 -0
- data/spec/controllers/pages_controller_spec.rb +39 -0
- data/spec/dummy/db/schema.rb +10 -9
- data/spec/factories.rb +5 -0
- data/spec/helpers/elements_helper_spec.rb +7 -0
- data/spec/integration/pages_controller_spec.rb +1 -1
- data/spec/models/element_spec.rb +51 -5
- data/spec/models/page_spec.rb +70 -10
- metadata +10 -7
- data/TODO.txt +0 -1
data/app/helpers/pages_helper.rb
CHANGED
@@ -488,16 +488,6 @@ module PagesHelper
|
|
488
488
|
render :partial => "cells/#{name}", :locals => {:cell => cell}
|
489
489
|
end
|
490
490
|
|
491
|
-
# Renders all element partials from given cell.
|
492
|
-
def render_cell_elements(cell)
|
493
|
-
return warning("No cell given.") if cell.blank?
|
494
|
-
ret = ""
|
495
|
-
cell.elements.each do |element|
|
496
|
-
ret << render_element(element)
|
497
|
-
end
|
498
|
-
ret.html_safe
|
499
|
-
end
|
500
|
-
|
501
491
|
# Returns true or false if no elements are in the cell found by name.
|
502
492
|
def cell_empty?(name)
|
503
493
|
cell = @page.cells.find_by_name(name)
|
data/app/models/element.rb
CHANGED
@@ -52,9 +52,11 @@ class Element < ActiveRecord::Base
|
|
52
52
|
|
53
53
|
# nullifies the page_id aka. trashs it.
|
54
54
|
def trash
|
55
|
-
self.
|
56
|
-
|
57
|
-
|
55
|
+
self.update_attributes({
|
56
|
+
:page_id => nil,
|
57
|
+
:folded => true,
|
58
|
+
:public => false
|
59
|
+
})
|
58
60
|
end
|
59
61
|
|
60
62
|
def trashed?
|
@@ -77,9 +79,39 @@ class Element < ActiveRecord::Base
|
|
77
79
|
self.contents.find_all_by_essence_type(essence_type)
|
78
80
|
end
|
79
81
|
|
82
|
+
# Returns the content that is marked as rss title.
|
83
|
+
#
|
84
|
+
# Mark a content as rss title in your +elements.yml+ file:
|
85
|
+
#
|
86
|
+
# - name: news
|
87
|
+
# contents:
|
88
|
+
# - name: headline
|
89
|
+
# type: EssenceText
|
90
|
+
# rss_title: true
|
91
|
+
#
|
92
|
+
def content_for_rss_title
|
93
|
+
rss_title = content_descriptions.detect { |c| c['rss_title'] }
|
94
|
+
contents.find_by_name(rss_title['name'])
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the content that is marked as rss description.
|
98
|
+
#
|
99
|
+
# Mark a content as rss description in your +elements.yml+ file:
|
100
|
+
#
|
101
|
+
# - name: news
|
102
|
+
# contents:
|
103
|
+
# - name: body
|
104
|
+
# type: EssenceRichtext
|
105
|
+
# rss_description: true
|
106
|
+
#
|
107
|
+
def content_for_rss_description
|
108
|
+
rss_title = content_descriptions.detect { |c| c['rss_description'] }
|
109
|
+
contents.find_by_name(rss_title['name'])
|
110
|
+
end
|
111
|
+
|
80
112
|
# Inits a new element for page as described in /config/alchemy/elements.yml from element_name
|
81
113
|
def self.new_from_scratch(attributes)
|
82
|
-
attributes.stringify_keys!
|
114
|
+
attributes.stringify_keys!
|
83
115
|
return Element.new if attributes['name'].blank?
|
84
116
|
element_descriptions = Element.descriptions
|
85
117
|
return if element_descriptions.blank?
|
@@ -162,8 +194,9 @@ class Element < ActiveRecord::Base
|
|
162
194
|
|
163
195
|
# returns the description of the element with my name in element.yml
|
164
196
|
def description
|
165
|
-
|
197
|
+
self.class.descriptions.detect{ |d| d['name'] == self.name }
|
166
198
|
end
|
199
|
+
alias_method :definition, :description
|
167
200
|
|
168
201
|
# Human name for displaying in selectboxes and element editor views.
|
169
202
|
# The name is beeing translated from elements name value as described in config/alchemy/elements.yml
|
@@ -379,6 +412,7 @@ private
|
|
379
412
|
|
380
413
|
# List all elements for page_layout
|
381
414
|
def self.all_for_page(page)
|
415
|
+
raise TypeError if page.class != Page
|
382
416
|
# if page_layout has cells, collect elements from cells and group them by cellname
|
383
417
|
page_layout = Alchemy::PageLayout.get(page.page_layout)
|
384
418
|
if page_layout.blank?
|
data/app/models/page.rb
CHANGED
@@ -35,6 +35,7 @@ class Page < ActiveRecord::Base
|
|
35
35
|
scope :language_roots, where(:language_root => true)
|
36
36
|
scope :layoutpages, where(:layoutpage => true)
|
37
37
|
scope :all_locked, where(:locked => true)
|
38
|
+
scope :not_locked, where(:locked => false)
|
38
39
|
scope :visible, where(:visible => true)
|
39
40
|
scope :public, where(:public => true)
|
40
41
|
scope :accessable, where(:restricted => false)
|
@@ -43,10 +44,13 @@ class Page < ActiveRecord::Base
|
|
43
44
|
where(:language_root => true).where("language_code IN ('#{Language.all_codes_for_published.join('\',\'')}')").where(:public => true)
|
44
45
|
}
|
45
46
|
scope :all_last_edited_from, lambda { |user| where(:updater_id => user.id).order('updated_at DESC').limit(5) }
|
46
|
-
|
47
|
-
|
47
|
+
|
48
|
+
# Returns all pages that have the given language_id
|
49
|
+
scope :with_language, lambda { |language_id| where(:language_id => language_id) }
|
50
|
+
|
51
|
+
# Returns all pages that are not locked and public.
|
48
52
|
# Used for flushing all page caches at once.
|
49
|
-
scope :flushables,
|
53
|
+
scope :flushables, public.not_locked
|
50
54
|
|
51
55
|
scope :contentpages, where("pages.layoutpage = 0 AND pages.parent_id IS NOT NULL")
|
52
56
|
|
@@ -59,12 +63,17 @@ class Page < ActiveRecord::Base
|
|
59
63
|
# :count => Integer # Limit the count of returned elements
|
60
64
|
# :offset => Integer # Starts with an offset while returning elements
|
61
65
|
# :random => Boolean # Returning elements randomly shuffled
|
66
|
+
# :from_cell => Cell # Returning elements from given cell
|
62
67
|
#
|
63
68
|
# Returns only public elements by default.
|
64
69
|
# Pass true as second argument to get all elements.
|
65
70
|
#
|
66
71
|
def find_selected_elements(options = {}, show_non_public = false)
|
67
|
-
|
72
|
+
if options[:from_cell].class.name == 'Cell'
|
73
|
+
elements = options[:from_cell].elements
|
74
|
+
else
|
75
|
+
elements = self.elements
|
76
|
+
end
|
68
77
|
if !options[:only].blank?
|
69
78
|
elements = self.elements.named(options[:only])
|
70
79
|
elsif !options[:except].blank?
|
@@ -82,13 +91,24 @@ class Page < ActiveRecord::Base
|
|
82
91
|
def find_elements(options = {}, show_non_public = false) #:nodoc:
|
83
92
|
# TODO: What is this? A Kind of proxy method? Why not rendering the elements directly if you already have them????
|
84
93
|
if !options[:collection].blank? && options[:collection].is_a?(Array)
|
85
|
-
|
94
|
+
return options[:collection]
|
86
95
|
else
|
87
|
-
|
96
|
+
find_selected_elements(options, show_non_public)
|
88
97
|
end
|
89
|
-
all_elements
|
90
98
|
end
|
91
99
|
|
100
|
+
# Returns all elements that should be feeded via rss.
|
101
|
+
#
|
102
|
+
# Define feedable elements in your +page_layouts.yml+:
|
103
|
+
#
|
104
|
+
# - name: news
|
105
|
+
# feed: true
|
106
|
+
# feed_elements: [element_name, element_2_name]
|
107
|
+
#
|
108
|
+
def feed_elements
|
109
|
+
elements.find_all_by_name(definition['feed_elements'])
|
110
|
+
end
|
111
|
+
|
92
112
|
def elements_grouped_by_cells
|
93
113
|
group = ActiveSupport::OrderedHash.new
|
94
114
|
cells.each { |cell| group[cell] = cell.elements }
|
@@ -1,19 +1,33 @@
|
|
1
1
|
(function($) {
|
2
|
+
|
2
3
|
Alchemy.closeCurrentWindow();
|
4
|
+
|
3
5
|
<%- if request.referer.include?('edit') -%>
|
6
|
+
|
4
7
|
Alchemy.reloadPreview();
|
5
8
|
$('#<%= dom_id(@page) -%>_status').replaceWith('<%= escape_javascript(render(:partial => "page_status")) -%>');
|
9
|
+
|
6
10
|
<%- else -%>
|
11
|
+
|
7
12
|
$('#<%= dom_id(@page) -%> > .sitemap_page > .sitemap_sitename .sitemap_pagename_link').text('<%= @page.name -%>');
|
13
|
+
|
8
14
|
<%- if @page.locked? && @page.locker == current_user -%>
|
9
15
|
$('#locked_page_<%= @page.id -%> > a').text('<%= @page.name -%>');
|
10
16
|
<%- end -%>
|
17
|
+
|
11
18
|
$('#page_<%= @page.id -%>_infos').html('<%= escape_javascript(render(:partial => "page_infos", :locals => {:page => @page})) -%>');
|
19
|
+
|
12
20
|
<%- if @page.restricted? -%>
|
21
|
+
|
13
22
|
$('#<%= dom_id(@page) -%> .page_status:nth-child(3)').addClass('restricted', 'not_restricted').removeClass('not_restricted');
|
23
|
+
|
14
24
|
<%- else -%>
|
25
|
+
|
15
26
|
$('#<%= dom_id(@page) -%> .page_status:nth-child(3)').addClass('not_restricted').removeClass('restricted');
|
16
27
|
<%- end -%>
|
28
|
+
|
17
29
|
<%- end -%>
|
18
|
-
|
30
|
+
|
31
|
+
Alchemy.growl("<%= @notice -%>");
|
32
|
+
|
19
33
|
})(jQuery);
|
@@ -22,7 +22,7 @@
|
|
22
22
|
<%- end -%>
|
23
23
|
<p style="margin-top: 8px" id="choose_alternative_uploader">
|
24
24
|
<small>
|
25
|
-
<%= raw _('If you have any problems using the Flash® uploader you can switch to the %{link}') % {:link => %(<a href="#" onclick="jQuery('#choose_alternative_uploader').hide();jQuery('#alternativeUpload').show();jQuery('
|
25
|
+
<%= raw _('If you have any problems using the Flash® uploader you can switch to the %{link}') % {:link => %(<a href="#" onclick="jQuery('#choose_alternative_uploader').hide();jQuery('#alternativeUpload').show();jQuery('object.swfupload').hide();" style="text-decoration: underline">%{value}</a>) % {:value => _('regular method')}} %>
|
26
26
|
</small>
|
27
27
|
</p>
|
28
28
|
<div id="swfUploadFlashError" style="display: none">
|
@@ -46,7 +46,7 @@
|
|
46
46
|
<p>
|
47
47
|
<small>
|
48
48
|
<a href="#"
|
49
|
-
onclick="jQuery('#choose_alternative_uploader').show();jQuery('#alternativeUpload').hide();jQuery('
|
49
|
+
onclick="jQuery('#choose_alternative_uploader').show();jQuery('#alternativeUpload').hide();jQuery('object.swfupload').show();"
|
50
50
|
style="text-decoration: underline">
|
51
51
|
<%= _('Switch to Flash® Uploader') %>
|
52
52
|
</a>
|
@@ -1,13 +1,11 @@
|
|
1
|
-
<%= form_for(@
|
1
|
+
<%= form_for(@message ||= Message.new, :html => {:id => "contact", "data-alchemy-element" => (@preview_mode ? element.id : nil)}) do |f| %>
|
2
2
|
<%= f.error_messages %>
|
3
3
|
<%= f.hidden_field "contact_form_id", :value => element.id %>
|
4
4
|
<%= hidden_field_tag "mail_to", params[:mail_to] %>
|
5
5
|
<table class="contactform">
|
6
6
|
<tr>
|
7
7
|
<td class="label">
|
8
|
-
|
9
|
-
<%= t('alchemy.contactform.labels.salutation') %>
|
10
|
-
</label>
|
8
|
+
<%= f.label :salutation, t('alchemy.contactform.labels.salutation') %>
|
11
9
|
</td>
|
12
10
|
<td class="field">
|
13
11
|
<%= f.select(
|
@@ -23,9 +21,7 @@
|
|
23
21
|
</tr>
|
24
22
|
<tr>
|
25
23
|
<td class="label">
|
26
|
-
|
27
|
-
<%= t('alchemy.contactform.labels.firstname') %>
|
28
|
-
</label>
|
24
|
+
<%= f.label :firstname, t('alchemy.contactform.labels.firstname') %>
|
29
25
|
</td>
|
30
26
|
<td class="field">
|
31
27
|
<%= f.text_field(:firstname, :class => "field") %>
|
@@ -33,9 +29,7 @@
|
|
33
29
|
</tr>
|
34
30
|
<tr>
|
35
31
|
<td class="label">
|
36
|
-
|
37
|
-
<%= t('alchemy.contactform.labels.lastname') %>
|
38
|
-
</label><small>*</small>
|
32
|
+
<%= f.label :lastname, (t('alchemy.contactform.labels.lastname') + '<small>*</small>').html_safe %>
|
39
33
|
</td>
|
40
34
|
<td class="field">
|
41
35
|
<%= f.text_field(:lastname, :class => "field") %>
|
@@ -43,9 +37,7 @@
|
|
43
37
|
</tr>
|
44
38
|
<tr>
|
45
39
|
<td class="label">
|
46
|
-
|
47
|
-
<%= t('alchemy.contactform.labels.address') %>
|
48
|
-
</label>
|
40
|
+
<%= f.label :address, t('alchemy.contactform.labels.address') %>
|
49
41
|
</td>
|
50
42
|
<td class="field">
|
51
43
|
<%= f.text_field :address, :class => 'field' %>
|
@@ -53,9 +45,7 @@
|
|
53
45
|
</tr>
|
54
46
|
<tr>
|
55
47
|
<td class="label">
|
56
|
-
|
57
|
-
<%= t('alchemy.contactform.labels.zip') %>
|
58
|
-
</label>
|
48
|
+
<%= f.label :zip, t('alchemy.contactform.labels.zip') %>
|
59
49
|
</td>
|
60
50
|
<td class="field">
|
61
51
|
<%= f.text_field :zip, :class => 'field short' %>
|
@@ -64,9 +54,7 @@
|
|
64
54
|
</tr>
|
65
55
|
<tr>
|
66
56
|
<td class="label">
|
67
|
-
|
68
|
-
<%= t('alchemy.contactform.labels.phone') %>
|
69
|
-
</label>
|
57
|
+
<%= f.label :phone, t('alchemy.contactform.labels.phone') %>
|
70
58
|
</td>
|
71
59
|
<td class="field">
|
72
60
|
<%= f.text_field :phone, :class => 'field' %>
|
@@ -74,9 +62,7 @@
|
|
74
62
|
</tr>
|
75
63
|
<tr>
|
76
64
|
<td class="label">
|
77
|
-
|
78
|
-
<%= t('alchemy.contactform.labels.email') %>
|
79
|
-
</label><small>*</small>
|
65
|
+
<%= f.label :email, (t('alchemy.contactform.labels.email') + '<small>*</small>').html_safe %>
|
80
66
|
</td>
|
81
67
|
<td class="field">
|
82
68
|
<%= f.text_field :email, :class => 'field' %>
|
@@ -84,8 +70,9 @@
|
|
84
70
|
</tr>
|
85
71
|
</table>
|
86
72
|
<div id="message">
|
87
|
-
|
73
|
+
<%= f.text_area :message %>
|
88
74
|
</div>
|
75
|
+
<p class="foot_notice">*) <%= t('alchemy.contactform.labels.mandatory_fields') %></p>
|
89
76
|
<p class="right">
|
90
77
|
<%= f.button t('alchemy.contactform.labels.send'), :name => nil, :class => 'button' %>
|
91
78
|
</p>
|
@@ -1,42 +1,49 @@
|
|
1
1
|
<div class="searchresult" id="<%= element_dom_id(element) %>" <%= element_preview_code(element) -%>>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
2
|
+
|
3
|
+
<%= form_tag show_page_path(:urlname => "suche", :lang => @page.language_code), :method => :get do %>
|
4
|
+
<%= text_field_tag "query", params[:query], :class => 'field' %>
|
5
|
+
<%= submit_tag _("search"), :name => nil %>
|
6
|
+
<%- end -%>
|
7
|
+
|
8
|
+
<%- if !@search_results.blank? -%>
|
9
|
+
|
10
|
+
<h2>
|
11
|
+
<%= t('alchemy.search.result_heading') % { :query => h(params[:query]), :count => @search_results.count } %>
|
12
|
+
</h2>
|
13
|
+
|
14
|
+
<div class="search_results">
|
15
|
+
<ul>
|
16
|
+
<%- @search_results.each do |result| -%>
|
17
|
+
<%- element = Content.find_by_essence_id_and_essence_type(result.id, result.class.to_s).element -%>
|
18
|
+
<%- page = element.nil? ? nil : element.page -%>
|
19
|
+
<li>
|
20
|
+
<%- unless page.nil? -%>
|
21
|
+
<h3>
|
22
|
+
<span class="search_result_site"><%= _('Page') %>:</span>
|
23
|
+
<%- if multi_language? -%>
|
24
|
+
<%= link_to page.name, show_page_path(:urlname => page.urlname, :lang => page.language_code) %>
|
25
|
+
<span class="search_result_language">(<%= page.language_code.upcase %>)</span>
|
26
|
+
<%- else -%>
|
27
|
+
<%= link_to page.name, show_page_path(:urlname => page.urlname) %>
|
28
|
+
<%- end -%>
|
29
|
+
</h3>
|
30
|
+
<%- end -%>
|
31
|
+
<h4><%= _('Excerpt') %>:</h4>
|
32
|
+
<%- result.highlight(
|
33
|
+
"*#{params[:query]}*", {
|
34
|
+
:field => (result.class == EssenceRichtext ? :stripped_body : :body)
|
35
|
+
}
|
36
|
+
).each do |highlight| -%>
|
37
|
+
<p><%= sanitize highlight %></p>
|
38
|
+
<%- end -%>
|
39
|
+
</li>
|
40
|
+
<%- end -%>
|
41
|
+
</ul>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<%- elsif !params[:query].blank? -%>
|
45
|
+
|
46
|
+
<h2><%= t('alchemy.search.no_results') %></h2>
|
47
|
+
|
48
|
+
<%- end -%>
|
42
49
|
</div>
|
@@ -1 +1 @@
|
|
1
|
-
<%= content.essence.source %>
|
1
|
+
<%= raw content.essence.source %>
|
@@ -1,27 +1,22 @@
|
|
1
|
-
xml.instruct! :xml, :version => "1.0"
|
1
|
+
xml.instruct! :xml, :version => "1.0"
|
2
2
|
xml.rss :version => "2.0" do
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
xml.guid show_page_url(:urlname => element.page.urlname, :anchor => element_dom_id(element))
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
3
|
+
|
4
|
+
xml.channel do
|
5
|
+
|
6
|
+
xml.title @page.title
|
7
|
+
xml.description @page.meta_description
|
8
|
+
xml.link show_page_url(:urlname => @page.urlname, :lang => multi_language? ? @page.language_code : nil)
|
9
|
+
|
10
|
+
@page.feed_elements.each do |element|
|
11
|
+
xml.item do
|
12
|
+
xml.title element.content_for_rss_title.ingredient
|
13
|
+
xml.description element.content_for_rss_description.ingredient
|
14
|
+
xml.pubDate render_essence_view_by_name(element, 'date', :date_format => :rfc822)
|
15
|
+
xml.link show_page_url(:urlname => @page.urlname, :anchor => element_dom_id(element), :lang => multi_language? ? @page.language_code : nil)
|
16
|
+
xml.guid show_page_url(:urlname => @page.urlname, :anchor => element_dom_id(element), :lang => multi_language? ? @page.language_code : nil)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
27
22
|
end
|