alchemy_cms 2.0.rc6 → 2.0
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/.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
|