summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-06-27 22:52:50 +0200
committererdgeist <erdgeist@erdgeist.org>2026-06-27 22:52:50 +0200
commit9a19a0494ef51cdac9a78e24d517ca48ba44c453 (patch)
tree8eaae12d8047a40e29d3ea7ff3116b5c869e04bd /app
parent85a01e35274b8d4d4165a7b26bd7986e211246bb (diff)
parent1853082fcd8c067390c246f9daa01a9b47387497 (diff)
Migration from Rails 2.3.5 to Rails 8.1 successful.
Merging dev branch.
Diffstat (limited to 'app')
-rw-r--r--app/assets/config/manifest.js1
-rw-r--r--app/assets/javascripts/admin_bundle.js5
-rwxr-xr-xapp/assets/javascripts/jquery.hotkeys.js244
-rw-r--r--app/controllers/admin_controller.rb48
-rw-r--r--app/controllers/application_controller.rb35
-rw-r--r--app/controllers/assets_controller.rb19
-rw-r--r--app/controllers/content_controller.rb39
-rw-r--r--app/controllers/events_controller.rb12
-rw-r--r--app/controllers/menu_items_controller.rb19
-rw-r--r--app/controllers/nodes_controller.rb49
-rw-r--r--app/controllers/occurrences_controller.rb13
-rw-r--r--app/controllers/pages_controller.rb16
-rw-r--r--app/controllers/revisions_controller.rb3
-rw-r--r--app/controllers/rss_controller.rb30
-rw-r--r--app/controllers/tags_controller.rb53
-rw-r--r--app/controllers/users_controller.rb23
-rw-r--r--app/helpers/admin_helper.rb8
-rw-r--r--app/helpers/application_helper.rb11
-rw-r--r--app/helpers/content_helper.rb44
-rw-r--r--app/helpers/link_helper.rb62
-rw-r--r--app/helpers/nodes_helper.rb20
-rw-r--r--app/models/application_record.rb3
-rw-r--r--app/models/asset.rb43
-rw-r--r--app/models/concerns/file_attachment.rb139
-rw-r--r--app/models/event.rb14
-rw-r--r--app/models/locked_by_another_user.rb1
-rw-r--r--app/models/menu_item.rb10
-rw-r--r--app/models/node.rb110
-rw-r--r--app/models/occurrence.rb27
-rw-r--r--app/models/page.rb104
-rw-r--r--app/models/permission.rb6
-rw-r--r--app/models/related_asset.rb8
-rw-r--r--app/models/user.rb4
-rw-r--r--app/views/admin/_drafts.html.erb4
-rw-r--r--app/views/admin/_menu.html.erb6
-rw-r--r--app/views/admin/_recent_changes.html.erb2
-rw-r--r--app/views/admin/index.html.erb85
-rw-r--r--app/views/admin/search_results.html.erb7
-rw-r--r--app/views/assets/edit.html.erb20
-rw-r--r--app/views/assets/index.html.erb6
-rw-r--r--app/views/assets/new.html.erb6
-rw-r--r--app/views/assets/show.html.erb4
-rw-r--r--app/views/content/_featured_articles.html.erb47
-rw-r--r--app/views/content/_main_navigation.html.erb2
-rw-r--r--app/views/content/_search.html.erb11
-rw-r--r--app/views/content/_tags.html.erb6
-rw-r--r--app/views/custom/page_templates/public/no_date_and_author.html.erb4
-rw-r--r--app/views/custom/page_templates/public/no_date_and_author_with_map.html.erb8
-rw-r--r--app/views/custom/page_templates/public/no_title_abstract_date_and_author.html.erb4
-rw-r--r--app/views/custom/page_templates/public/standard_template.html.erb4
-rw-r--r--app/views/custom/page_templates/public/title_only.html.erb4
-rw-r--r--app/views/custom/page_templates/public/update.html.erb4
-rw-r--r--app/views/custom/partials/_article.html.erb4
-rw-r--r--app/views/custom/partials/_no_date_and_author.html.erb4
-rw-r--r--app/views/events/edit.html.erb6
-rw-r--r--app/views/events/index.html.erb4
-rw-r--r--app/views/events/new.html.erb6
-rw-r--r--app/views/layouts/admin.html.erb15
-rw-r--r--app/views/layouts/application.html.erb68
-rw-r--r--app/views/layouts/pages.html.erb2
-rw-r--r--app/views/menu_items/edit.html.erb4
-rw-r--r--app/views/menu_items/index.html.erb11
-rw-r--r--app/views/menu_items/new.html.erb4
-rw-r--r--app/views/nodes/edit.html.erb168
-rw-r--r--app/views/nodes/index.html.erb2
-rw-r--r--app/views/nodes/new.html.erb21
-rw-r--r--app/views/nodes/update.js.erb8
-rw-r--r--app/views/occurrences/edit.html.erb6
-rw-r--r--app/views/occurrences/index.html.erb4
-rw-r--r--app/views/occurrences/new.html.erb6
-rw-r--r--app/views/pages/edit.html.erb4
-rw-r--r--app/views/pages/index.html.erb4
-rw-r--r--app/views/pages/new.html.erb4
-rw-r--r--app/views/revisions/diff.html.erb6
-rw-r--r--app/views/revisions/index.html.erb40
-rw-r--r--app/views/rss/recent_changes.xml.builder8
-rw-r--r--app/views/rss/updates.rdf.builder22
-rw-r--r--app/views/rss/updates.xml.builder11
-rw-r--r--app/views/search/_search_result.html.erb6
-rw-r--r--app/views/sessions/new.html.erb4
-rw-r--r--app/views/users/_user.html.erb11
-rw-r--r--app/views/users/edit.html.erb11
-rw-r--r--app/views/users/new.html.erb11
83 files changed, 1305 insertions, 637 deletions
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
new file mode 100644
index 0000000..56d7f6d
--- /dev/null
+++ b/app/assets/config/manifest.js
@@ -0,0 +1 @@
//= link admin_bundle.js
diff --git a/app/assets/javascripts/admin_bundle.js b/app/assets/javascripts/admin_bundle.js
new file mode 100644
index 0000000..687266c
--- /dev/null
+++ b/app/assets/javascripts/admin_bundle.js
@@ -0,0 +1,5 @@
1//= require jquery
2//= require jquery_ujs
3//= require jquery-ui
4//= require jquery.hotkeys
5//= require_self
diff --git a/app/assets/javascripts/jquery.hotkeys.js b/app/assets/javascripts/jquery.hotkeys.js
new file mode 100755
index 0000000..9a8f2de
--- /dev/null
+++ b/app/assets/javascripts/jquery.hotkeys.js
@@ -0,0 +1,244 @@
1/*
2(c) Copyrights 2007 - 2008
3
4Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
5
6jQuery Plugin by Tzury Bar Yochay
7tzury.by@gmail.com
8http://evalinux.wordpress.com
9http://facebook.com/profile.php?id=513676303
10
11Project's sites:
12http://code.google.com/p/js-hotkeys/
13http://github.com/tzuryby/hotkeys/tree/master
14
15License: same as jQuery license.
16
17USAGE:
18 // simple usage
19 $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
20
21 // special options such as disableInIput
22 $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
23
24Note:
25 This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
26*/
27
28(function (jQuery){
29 // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find
30 jQuery.fn.__bind__ = jQuery.fn.bind;
31 jQuery.fn.__unbind__ = jQuery.fn.unbind;
32 jQuery.fn.__find__ = jQuery.fn.find;
33
34 var hotkeys = {
35 version: '0.7.9',
36 override: /keypress|keydown|keyup/g,
37 triggersMap: {},
38
39 specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll',
40 20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
41 35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down',
42 109: '-',
43 112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8',
44 120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
45
46 shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&",
47 "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<",
48 ".":">", "/":"?", "\\":"|" },
49
50 newTrigger: function (type, combi, callback) {
51 // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
52 var result = {};
53 result[type] = {};
54 result[type][combi] = {cb: callback, disableInInput: false};
55 return result;
56 }
57 };
58 // add firefox num pad char codes
59 //if (jQuery.browser.mozilla){
60 // add num pad char codes
61 hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99:
62 '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*',
63 107: '+', 109: '-', 110: '.', 111 : '/'
64 });
65 //}
66
67 // a wrapper around of $.fn.find
68 // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
69 jQuery.fn.find = function( selector ) {
70 this.query = selector;
71 return jQuery.fn.__find__.apply(this, arguments);
72 };
73
74 jQuery.fn.unbind = function (type, combi, fn){
75 if (jQuery.isFunction(combi)){
76 fn = combi;
77 combi = null;
78 }
79 if (combi && typeof combi === 'string'){
80 var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
81 var hkTypes = type.split(' ');
82 for (var x=0; x<hkTypes.length; x++){
83 delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
84 }
85 }
86 // call jQuery original unbind
87 return this.__unbind__(type, fn);
88 };
89
90 jQuery.fn.bind = function(type, data, fn){
91 // grab keyup,keydown,keypress
92 var handle = type.match(hotkeys.override);
93
94 if (jQuery.isFunction(data) || !handle){
95 // call jQuery.bind only
96 return this.__bind__(type, data, fn);
97 }
98 else{
99 // split the job
100 var result = null,
101 // pass the rest to the original $.fn.bind
102 pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
103
104 // see if there are other types, pass them to the original $.fn.bind
105 if (pass2jq){
106 result = this.__bind__(pass2jq, data, fn);
107 }
108
109 if (typeof data === "string"){
110 data = {'combi': data};
111 }
112 if(data.combi){
113 for (var x=0; x < handle.length; x++){
114 var eventType = handle[x];
115 var combi = data.combi.toLowerCase(),
116 trigger = hotkeys.newTrigger(eventType, combi, fn),
117 selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
118
119 //trigger[eventType][combi].propagate = data.propagate;
120 trigger[eventType][combi].disableInInput = data.disableInInput;
121
122 // first time selector is bounded
123 if (!hotkeys.triggersMap[selectorId]) {
124 hotkeys.triggersMap[selectorId] = trigger;
125 }
126 // first time selector is bounded with this type
127 else if (!hotkeys.triggersMap[selectorId][eventType]) {
128 hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
129 }
130 // make trigger point as array so more than one handler can be bound
131 var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
132 if (!mapPoint){
133 hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
134 }
135 else if (mapPoint.constructor !== Array){
136 hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
137 }
138 else {
139 hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
140 }
141
142 // add attribute and call $.event.add per matched element
143 this.each(function(){
144 // jQuery wrapper for the current element
145 var jqElem = jQuery(this);
146
147 // element already associated with another collection
148 if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
149 selectorId = jqElem.attr('hkId') + ";" + selectorId;
150 }
151 jqElem.attr('hkId', selectorId);
152 });
153 result = this.__bind__(handle.join(' '), data, hotkeys.handler)
154 }
155 }
156 return result;
157 }
158 };
159 // work-around for opera and safari where (sometimes) the target is the element which was last
160 // clicked with the mouse and not the document event it would make sense to get the document
161 hotkeys.findElement = function (elem){
162 if (!jQuery(elem).attr('hkId')){
163 if (jQuery.browser.opera || jQuery.browser.safari){
164 while (!jQuery(elem).attr('hkId') && elem.parentNode){
165 elem = elem.parentNode;
166 }
167 }
168 }
169 return elem;
170 };
171 // the event handler
172 hotkeys.handler = function(event) {
173 var target = hotkeys.findElement(event.currentTarget),
174 jTarget = jQuery(target),
175 ids = jTarget.attr('hkId');
176
177 if(ids){
178 ids = ids.split(';');
179 var code = event.which,
180 type = event.type,
181 special = hotkeys.specialKeys[code],
182 // prevent f5 overlapping with 't' (or f4 with 's', etc.)
183 character = !special && String.fromCharCode(code).toLowerCase(),
184 shift = event.shiftKey,
185 ctrl = event.ctrlKey,
186 // patch for jquery 1.2.5 && 1.2.6 see more at:
187 // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
188 alt = event.altKey || event.originalEvent.altKey,
189 mapPoint = null;
190
191 for (var x=0; x < ids.length; x++){
192 if (hotkeys.triggersMap[ids[x]][type]){
193 mapPoint = hotkeys.triggersMap[ids[x]][type];
194 break;
195 }
196 }
197
198 //find by: id.type.combi.options
199 if (mapPoint){
200 var trigger;
201 // event type is associated with the hkId
202 if(!shift && !ctrl && !alt) { // No Modifiers
203 trigger = mapPoint[special] || (character && mapPoint[character]);
204 }
205 else{
206 // check combinations (alt|ctrl|shift+anything)
207 var modif = '';
208 if(alt) modif +='alt+';
209 if(ctrl) modif+= 'ctrl+';
210 if(shift) modif += 'shift+';
211 // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
212 trigger = mapPoint[modif+special];
213 if (!trigger){
214 if (character){
215 trigger = mapPoint[modif+character]
216 || mapPoint[modif+hotkeys.shiftNums[character]]
217 // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
218 || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
219 }
220 }
221 }
222 if (trigger){
223 var result = false;
224 for (var x=0; x < trigger.length; x++){
225 if(trigger[x].disableInInput){
226 // double check event.currentTarget and event.target
227 var elem = jQuery(event.target);
228 if (jTarget.is("input") || jTarget.is("textarea") || jTarget.is("select")
229 || elem.is("input") || elem.is("textarea") || elem.is("select")) {
230 return true;
231 }
232 }
233 // call the registered callback function
234 result = result || trigger[x].cb.apply(this, [event]);
235 }
236 return result;
237 }
238 }
239 }
240 };
241 // place it under window so it can be extended and overridden by others
242 window.hotkeys = hotkeys;
243 return jQuery;
244})(jQuery);
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 1d1a1ca..9e8564e 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -2,31 +2,46 @@ class AdminController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 def index 7 def index
8 @drafts = Node.all( 8 @drafts = Node.where("draft_id IS NOT NULL")
9 :limit => 20, 9 .limit(50).order("updated_at desc")
10 :order => "updated_at desc", 10
11 :conditions => ["draft_id IS NOT NULL"] 11 @drafts_count = Node.where("draft_id IS NOT NULL").count
12 ) 12
13 @recent_changes = Node.all( 13 @recent_changes = Node.where(
14 :limit => 20, 14 "updated_at < ? AND updated_at > ? AND parent_id IS NOT NULL",
15 :order => "updated_at desc", 15 Time.now, Time.now - 14.days
16 :conditions => [ 16 ).limit(50).order("updated_at desc")
17 "updated_at < ? AND updated_at > ? AND parent_id IS NOT NULL", Time.now, Time.now-14.days 17
18 ] 18 all_nodes = Node.root.self_and_descendants
19 ) 19 @sitemap_depth = {}
20 Node.each_with_level(all_nodes) do |node, level|
21 @sitemap_depth[node.id] = level
22 end
23 @sitemap = all_nodes.to_a.sort! { |node1,node2| node1.lft <=> node2.lft }.delete_if { |node| node.update? }
24
25 @mypages = Page.where("user_id = ? or editor_id = ?", @current_user, @current_user)
26
27 @mynodes = Node.joins(:pages)
28 .where("pages.user_id = ? or pages.editor_id = ?", @current_user, @current_user)
29 .order("updated_at desc")
30 .uniq.first(50)
20 end 31 end
21 32
22 def search 33 def search
23 @results = Node.search params[:search_term] 34 @results = Node.search params[:search_term], :per_page => 1000
24 35
25 respond_to do |format| 36 respond_to do |format|
26 format.html 37 format.html do
38 render :template => 'admin/search_results.html'
39 end
27 format.js do 40 format.js do
28 render( :json => @results.map do |node| 41 render( :json => @results.map do |node|
29 {:id => node.id, :title => node.title, :edit_path => node_path(node)} 42 if node
43 {:id => node.id, :title => node.title, :edit_path => node_path(node)}
44 end
30 end 45 end
31 ) 46 )
32 47
@@ -46,7 +61,6 @@ class AdminController < ApplicationController
46 render :partial => 'admin/menu_search_results' 61 render :partial => 'admin/menu_search_results'
47 end 62 end
48 63
49
50 format.js do 64 format.js do
51 render( :json => @results.map do |node| 65 render( :json => @results.map do |node|
52 {:node_id => node.id, :title => node.title, :unique_name => node.unique_name} 66 {:node_id => node.id, :title => node.title, :unique_name => node.unique_name}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index bce0c71..75f92c3 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,26 +1,21 @@
1# Filters added to this controller apply to all controllers in the application.
2# Likewise, all the methods added will be available for all controllers.
3
4class ApplicationController < ActionController::Base 1class ApplicationController < ActionController::Base
5
6 include ExceptionNotifiable
7 include AuthenticatedSystem 2 include AuthenticatedSystem
8
9 helper :all # include all helpers, all the time
10 protect_from_forgery # See ActionController::RequestForgeryProtection for details
11 3
12 # Scrub sensitive parameters from your log 4 protect_from_forgery
13 filter_parameter_logging :password, :password_confirmation 5
14 6 before_action :set_locale
15 before_filter :set_locale 7
16
17 protected 8 protected
18 9
19 def set_locale 10 def set_locale
20 if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym) 11 if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
21 I18n.locale = params[:locale].to_sym 12 I18n.locale = params[:locale].to_sym
22 else 13 else
23 params.delete(:locale) 14 I18n.locale = I18n.default_locale
24 end
25 end 15 end
16 end
17
18 def default_url_options
19 { locale: I18n.locale == I18n.default_locale ? nil : I18n.locale }
20 end
26end 21end
diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb
index cfaf176..d150e06 100644
--- a/app/controllers/assets_controller.rb
+++ b/app/controllers/assets_controller.rb
@@ -2,15 +2,14 @@ class AssetsController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 layout 'admin' 7 layout 'admin'
8 8
9 def index 9 def index
10 @assets = Asset.all.paginate( 10 @assets = Asset.order('id DESC').paginate(
11 :page => params[:page], 11 :page => params[:page],
12 :per_page => 20, 12 :per_page => 20
13 :order => 'id DESC'
14 ) 13 )
15 end 14 end
16 15
@@ -44,7 +43,7 @@ class AssetsController < ApplicationController
44 # POST /assets 43 # POST /assets
45 # POST /assets.xml 44 # POST /assets.xml
46 def create 45 def create
47 @asset = Asset.new(params[:asset]) 46 @asset = Asset.new(asset_params)
48 47
49 respond_to do |format| 48 respond_to do |format|
50 if @asset.save 49 if @asset.save
@@ -64,7 +63,7 @@ class AssetsController < ApplicationController
64 @asset = Asset.find(params[:id]) 63 @asset = Asset.find(params[:id])
65 64
66 respond_to do |format| 65 respond_to do |format|
67 if @asset.update_attributes(params[:asset]) 66 if @asset.update(asset_params)
68 flash[:notice] = 'Asset was successfully updated.' 67 flash[:notice] = 'Asset was successfully updated.'
69 format.html { redirect_to(@asset) } 68 format.html { redirect_to(@asset) }
70 format.xml { head :ok } 69 format.xml { head :ok }
@@ -86,4 +85,10 @@ class AssetsController < ApplicationController
86 format.xml { head :ok } 85 format.xml { head :ok }
87 end 86 end
88 end 87 end
88
89 private
90
91 def asset_params
92 params.require(:asset).permit(:name, :upload)
93 end
89end 94end
diff --git a/app/controllers/content_controller.rb b/app/controllers/content_controller.rb
index 1b13456..8d33105 100644
--- a/app/controllers/content_controller.rb
+++ b/app/controllers/content_controller.rb
@@ -1,30 +1,31 @@
1class ContentController < ApplicationController 1class ContentController < ApplicationController
2 2
3 # Public 3 # Public
4 4
5 before_filter :find_page 5 before_action :find_page
6 6
7 # This is the method that renders most of the the public content. It recieves 7 # This is the method that renders most of the the public content. It recieves
8 # a :locale and a :page_path parameter through the params hash. It looks up 8 # a :locale and a :page_path parameter through the params hash. It looks up
9 # the node with the corresponding unique_name attribute. The method doesn't 9 # the node with the corresponding unique_name attribute. The method doesn't
10 # return a node though, the node is really a proxy object for pages. It 10 # return a node though, the node is really a proxy object for pages. It
11 # returns the most recent page associated to this node instead. 11 # returns the most recent page associated to this node instead.
12 def render_page 12 def render_page
13 13
14 expires_in 20.minutes, :public => true 14 expires_in 20.minutes, :public => true
15 15
16 if @page and @page.public? 16 if @page and @page.public?
17 render( 17 render(
18 :file => @page.valid_template, 18 :template => @page.valid_template,
19 :layout => true 19 :layout => true
20 ) 20 )
21 else 21 else
22 render( 22 render(
23 :file => File.join(RAILS_ROOT, 'public', '404.html'), 23 :file => Rails.root.join('public', '404.html').to_s,
24 :status => 404 24 :status => 404,
25 :layout => false
25 ) 26 )
26 end 27 end
27 28
28 end 29 end
29 30
30 def render_gallery 31 def render_gallery
@@ -32,13 +33,17 @@ class ContentController < ApplicationController
32 @images = @page.assets.images 33 @images = @page.assets.images
33 render :file => "content/gallery" 34 render :file => "content/gallery"
34 else 35 else
35 render :nothing => true, :status => 404 36 head :not_found
36 end 37 end
37 end 38 end
38 39
39 private 40 private
40 def find_page 41 def find_page
41 path = params[:page_path].join('/') 42 path = params[:page_path].is_a?(Array) ? params[:page_path].join('/') : params[:page_path]
42 @page = Node.find_page(path) 43 if path =~ /^[a-zA-Z\:\/\/\.\-\d_]+$/
44 @page = Node.find_page(path)
45 else
46 @page = nil
47 end
43 end 48 end
44end 49end
diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb
index 805e941..7695e9b 100644
--- a/app/controllers/events_controller.rb
+++ b/app/controllers/events_controller.rb
@@ -2,7 +2,7 @@ class EventsController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 layout 'admin' 7 layout 'admin'
8 8
@@ -47,7 +47,7 @@ class EventsController < ApplicationController
47 # POST /events 47 # POST /events
48 # POST /events.xml 48 # POST /events.xml
49 def create 49 def create
50 @event = Event.new(params[:event]) 50 @event = Event.new(event_params)
51 51
52 respond_to do |format| 52 respond_to do |format|
53 if @event.save 53 if @event.save
@@ -67,7 +67,7 @@ class EventsController < ApplicationController
67 @event = Event.find(params[:id]) 67 @event = Event.find(params[:id])
68 68
69 respond_to do |format| 69 respond_to do |format|
70 if @event.update_attributes(params[:event]) 70 if @event.update(event_params)
71 flash[:notice] = 'Event was successfully updated.' 71 flash[:notice] = 'Event was successfully updated.'
72 format.html { redirect_to(edit_node_path(@event.node)) } 72 format.html { redirect_to(edit_node_path(@event.node)) }
73 format.xml { head :ok } 73 format.xml { head :ok }
@@ -89,4 +89,10 @@ class EventsController < ApplicationController
89 format.xml { head :ok } 89 format.xml { head :ok }
90 end 90 end
91 end 91 end
92
93 private
94
95 def event_params
96 params.require(:event).permit(:start_time, :end_time, :rrule, :custom_rrule, :allday, :url, :latitude, :longitude, :node_id, :location)
97 end
92end 98end
diff --git a/app/controllers/menu_items_controller.rb b/app/controllers/menu_items_controller.rb
index 808da15..1b1eb59 100644
--- a/app/controllers/menu_items_controller.rb
+++ b/app/controllers/menu_items_controller.rb
@@ -2,23 +2,23 @@ class MenuItemsController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 layout 'admin' 7 layout 'admin'
8 8
9 def index 9 def index
10 @menu_items = MenuItem.all(:order => "position ASC") 10 @menu_items = MenuItem.order("position ASC").all
11 end 11 end
12 12
13 def show 13 def show
14 end 14 end
15 15
16 def new 16 def new
17 @menu_item = MenuItem.new params[:menu_item] 17 @menu_item = MenuItem.new menu_item_params
18 end 18 end
19 19
20 def create 20 def create
21 if MenuItem.create( params[:menu_item] ) 21 if MenuItem.create( menu_item_params )
22 redirect_to menu_items_path 22 redirect_to menu_items_path
23 else 23 else
24 render :new 24 render :new
@@ -32,7 +32,7 @@ class MenuItemsController < ApplicationController
32 def update 32 def update
33 @menu_item = MenuItem.find( params[:id] ) 33 @menu_item = MenuItem.find( params[:id] )
34 34
35 if @menu_item.update_attributes( params[:menu_item] ) 35 if @menu_item.update( menu_item_params )
36 redirect_to menu_items_path 36 redirect_to menu_items_path
37 else 37 else
38 render :edit 38 render :edit
@@ -48,10 +48,15 @@ class MenuItemsController < ApplicationController
48 def sort 48 def sort
49 params[:menu_items].each_with_index do |item_id, index| 49 params[:menu_items].each_with_index do |item_id, index|
50 menu_item = MenuItem.find(item_id) 50 menu_item = MenuItem.find(item_id)
51 menu_item.update_attributes(:position => index + 1) 51 menu_item.update(:position => index + 1)
52 end 52 end
53 53
54 render :nothing => true 54 head :ok
55 end 55 end
56 56
57 private
58
59 def menu_item_params
60 params.require(:menu_item).permit(:node_id, :path, :position, :type, :type_id)
61 end
57end 62end
diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb
index 4f72744..494887d 100644
--- a/app/controllers/nodes_controller.rb
+++ b/app/controllers/nodes_controller.rb
@@ -4,8 +4,8 @@ class NodesController < ApplicationController
4 4
5 layout 'admin' 5 layout 'admin'
6 6
7 before_filter :login_required 7 before_action :login_required
8 before_filter :find_node, :only => [ 8 before_action :find_node, :only => [
9 :show, 9 :show,
10 :edit, 10 :edit,
11 :update, 11 :update,
@@ -15,16 +15,17 @@ class NodesController < ApplicationController
15 ] 15 ]
16 16
17 def index 17 def index
18 @nodes = Node.root.descendants.paginate( 18 @nodes = Node.root.descendants.includes(:head, :draft)
19 :include => [:head, :draft], 19 .order('id DESC')
20 :page => params[:page], 20 .paginate(:page => params[:page], :per_page => 25)
21 :per_page => 25,
22 :order => 'id DESC'
23 )
24 end 21 end
25 22
26 def new 23 def new
27 @node = Node.new params[:node] 24 @node = Node.new node_params
25 if params.has_key?(:parent_id)
26 @parent_id = params[:parent_id]
27 @parent_name = Node.find(@parent_id).title
28 end
28 end 29 end
29 30
30 def create 31 def create
@@ -33,9 +34,16 @@ class NodesController < ApplicationController
33 @node = Node.new 34 @node = Node.new
34 @node.parent_id = find_parent 35 @node.parent_id = find_parent
35 @node.slug = params[:title].parameterize.to_s 36 @node.slug = params[:title].parameterize.to_s
36 37
37 if @node.save 38 if @node.save
38 @node.draft.update_attributes(:title => params[:title]) 39 @node.draft.update(:title => params[:title])
40 case params[:kind]
41 when "update"
42 @node.draft.tag_list.add("update")
43 when "press_release"
44 @node.draft.tag_list.add("update", "pressemitteilung")
45 end
46 @node.draft.save!
39 redirect_to(edit_node_path(@node)) 47 redirect_to(edit_node_path(@node))
40 else 48 else
41 render :new 49 render :new
@@ -44,6 +52,7 @@ class NodesController < ApplicationController
44 52
45 def show 53 def show
46 node = Node.find(params[:id]) 54 node = Node.find(params[:id])
55 node.wipe_draft!
47 @page = node.draft || node.head 56 @page = node.draft || node.head
48 end 57 end
49 58
@@ -53,7 +62,7 @@ class NodesController < ApplicationController
53 rescue LockedByAnotherUser => e 62 rescue LockedByAnotherUser => e
54 flash[:error] = e.message 63 flash[:error] = e.message
55 if request.referer 64 if request.referer
56 redirect_to :back 65 redirect_to request.referer || node_path(@node)
57 else 66 else
58 redirect_to node_path(@node) 67 redirect_to node_path(@node)
59 end 68 end
@@ -61,10 +70,10 @@ class NodesController < ApplicationController
61 end 70 end
62 71
63 def update 72 def update
64 @node.update_attributes(params[:node]) 73 @node.update(node_params)
65 @draft = @node.find_or_create_draft current_user 74 @draft = @node.find_or_create_draft current_user
66 @draft.tag_list = params[:tag_list] 75 @draft.tag_list = params[:tag_list]
67 if @draft.update_attributes( params[:page] ) 76 if @draft.update( page_params )
68 flash[:notice] = "Draft has been saved: #{Time.now}" 77 flash[:notice] = "Draft has been saved: #{Time.now}"
69 respond_to do |format| 78 respond_to do |format|
70 format.html { redirect_to edit_node_path(@node) } 79 format.html { redirect_to edit_node_path(@node) }
@@ -82,7 +91,7 @@ class NodesController < ApplicationController
82 def publish 91 def publish
83 @node.publish_draft! 92 @node.publish_draft!
84 flash[:notice] = "Draft has been published" 93 flash[:notice] = "Draft has been published"
85 redirect_to node_path 94 redirect_to node_path(@node)
86 end 95 end
87 96
88 def unlock 97 def unlock
@@ -96,6 +105,14 @@ class NodesController < ApplicationController
96 end 105 end
97 106
98 private 107 private
108
109 def node_params
110 params.fetch(:node, {}).permit(:slug, :parent_id, :staged_slug, :staged_parent_id)
111 end
112
113 def page_params
114 params.fetch(:page, {}).permit(:title, :abstract, :body, :template_name, :published_at, :user_id)
115 end
99 116
100 def find_node 117 def find_node
101 @node = Node.find(params[:id]) 118 @node = Node.find(params[:id])
@@ -107,6 +124,8 @@ class NodesController < ApplicationController
107 Node.root.id 124 Node.root.id
108 when "update" 125 when "update"
109 Update.find_or_create_parent.id 126 Update.find_or_create_parent.id
127 when "press_release"
128 Update.find_or_create_parent.id
110 when "generic" 129 when "generic"
111 if params[:parent_id] && Node.find(params[:parent_id]) 130 if params[:parent_id] && Node.find(params[:parent_id])
112 params[:parent_id] 131 params[:parent_id]
diff --git a/app/controllers/occurrences_controller.rb b/app/controllers/occurrences_controller.rb
index 751be40..0f30ce3 100644
--- a/app/controllers/occurrences_controller.rb
+++ b/app/controllers/occurrences_controller.rb
@@ -2,7 +2,7 @@ class OccurrencesController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 # GET /occurrences 7 # GET /occurrences
8 # GET /occurrences.xml 8 # GET /occurrences.xml
@@ -45,7 +45,7 @@ class OccurrencesController < ApplicationController
45 # POST /occurrences 45 # POST /occurrences
46 # POST /occurrences.xml 46 # POST /occurrences.xml
47 def create 47 def create
48 @occurrence = Occurrence.new(params[:occurrence]) 48 @occurrence = Occurrence.new(occurrence_params)
49 49
50 respond_to do |format| 50 respond_to do |format|
51 if @occurrence.save 51 if @occurrence.save
@@ -65,7 +65,7 @@ class OccurrencesController < ApplicationController
65 @occurrence = Occurrence.find(params[:id]) 65 @occurrence = Occurrence.find(params[:id])
66 66
67 respond_to do |format| 67 respond_to do |format|
68 if @occurrence.update_attributes(params[:occurrence]) 68 if @occurrence.update(occurrence_params)
69 flash[:notice] = 'Occurrence was successfully updated.' 69 flash[:notice] = 'Occurrence was successfully updated.'
70 format.html { redirect_to(@occurrence) } 70 format.html { redirect_to(@occurrence) }
71 format.xml { head :ok } 71 format.xml { head :ok }
@@ -87,4 +87,11 @@ class OccurrencesController < ApplicationController
87 format.xml { head :ok } 87 format.xml { head :ok }
88 end 88 end
89 end 89 end
90
91 private
92
93 def occurrence_params
94 params.require(:occurrence).permit(:start_time, :end_time, :node_id, :event_id)
95 end
96
90end 97end
diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb
index a684327..2d08dea 100644
--- a/app/controllers/pages_controller.rb
+++ b/app/controllers/pages_controller.rb
@@ -2,26 +2,24 @@ class PagesController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 def preview 7 def preview
8 @page = Page.find(params[:id]) 8 @page = Page.find(params[:id])
9 9
10 if @page 10 if @page
11 template = @page.valid_template 11 template = @page.valid_template
12 render( 12 render(
13 :file => template, 13 template: template,
14 :layout => "application" 14 layout: "application"
15 ) 15 )
16 end 16 end
17
18 end 17 end
19 18
20
21 def sort_images 19 def sort_images
22 page = Page.find(params[:id]) 20 page = Page.find(params[:id])
23 page.update_assets(params[:images]) 21 page.update_assets(params[:images])
24 22
25 render :nothing => true, :status => 200 23 head :ok
26 end 24 end
27end 25end
diff --git a/app/controllers/revisions_controller.rb b/app/controllers/revisions_controller.rb
index 05e8acc..42d667e 100644
--- a/app/controllers/revisions_controller.rb
+++ b/app/controllers/revisions_controller.rb
@@ -2,12 +2,13 @@ class RevisionsController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 6
7 layout 'admin' 7 layout 'admin'
8 8
9 def index 9 def index
10 @node = Node.find(params[:node_id]) 10 @node = Node.find(params[:node_id])
11 @pages = @node.pages.all
11 end 12 end
12 13
13 def diff 14 def diff
diff --git a/app/controllers/rss_controller.rb b/app/controllers/rss_controller.rb
index acffc0e..4b47218 100644
--- a/app/controllers/rss_controller.rb
+++ b/app/controllers/rss_controller.rb
@@ -1,19 +1,21 @@
1class RssController < ApplicationController 1class RssController < ApplicationController
2 2
3 before_filter :authenticate, :only => :recent_changes 3 before_action :authenticate, :only => :recent_changes
4 before_filter :get_host 4 before_action :get_host
5 5
6 def updates 6 def updates
7 expires_in 31.minutes, :public => true 7 expires_in 31.minutes, :public => true
8 8
9 I18n.locale = :de 9 I18n.locale = :de
10 10
11 @items = Page.heads.find_tagged_with( 11 @items = Page.heads
12 "update", 12 .joins("JOIN taggings ON taggings.taggable_id = pages.id
13 :order => "published_at DESC", 13 AND taggings.taggable_type = 'Page'
14 :limit => 20 14 AND taggings.context = 'tags'")
15 ) 15 .joins("JOIN tags ON tags.id = taggings.tag_id")
16 16 .where("LOWER(tags.name) = ?", "update")
17 .order("published_at DESC").limit(20)
18
17 respond_to do |format| 19 respond_to do |format|
18 format.xml {} 20 format.xml {}
19 format.rdf {} 21 format.rdf {}
@@ -21,13 +23,9 @@ class RssController < ApplicationController
21 end 23 end
22 24
23 def recent_changes 25 def recent_changes
24 @items = Page.all( 26 @items = Page.where(
25 :limit => 20, 27 "updated_at < ? AND updated_at > ?", Time.now, Time.now - 14.days
26 :order => "updated_at desc", 28 ).limit(20).order("updated_at desc")
27 :conditions => [
28 "updated_at < ? AND updated_at > ?", Time.now, Time.now-14.days
29 ]
30 )
31 end 29 end
32 30
33 protected 31 protected
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 565cdd4..bf6a029 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -1,33 +1,44 @@
1class TagsController < ApplicationController 1class TagsController < ApplicationController
2 2
3 # Public 3 # Public
4 4
5 def index 5 def index
6 @page = Page.new :title => "Tags" 6 @page = Page.new :title => "Tags"
7 7
8 @tags = Tag.all(:limit => 500) 8 @tags = Tag.limit(500).all
9 end 9 end
10 10
11 def show 11 def show
12 @tag = Tag.find_by_name(params[:id]) 12 tag_name = params[:id]
13 13
14 @tag = @tag ? @tag.name : params[:id] 14 if tag_name.match(/^[a-zA-Z0-9_\w\s\-\.\']+$/)
15 15 @tag = ActsAsTaggableOn::Tag.find_by_name(tag_name)
16 @page = Page.new 16 @tag = @tag ? @tag.name : tag_name
17 @page = Page.new
17 18
18 params[:page] = ( params[:page].is_a?(Fixnum) ? params[:page] : 1 ) 19 params[:page] = (params[:page].is_a?(Integer) ? params[:page] : 1)
19 20
20 @pages = Page.heads.paginate( 21 @pages = Page.heads
21 Page.find_options_for_find_tagged_with(@tag).merge( 22 .joins("JOIN taggings ON taggings.taggable_id = pages.id
22 :order => 'published_at DESC', 23 AND taggings.taggable_type = 'Page'
23 :page=>params[:page], 24 AND taggings.context = 'tags'")
24 :per_page => 23 25 .joins("JOIN tags ON tags.id = taggings.tag_id")
25 ) 26 .where("LOWER(tags.name) = ?", @tag.downcase)
26 ) 27 .order('published_at DESC')
27 28 .paginate(
28 respond_to do |format| 29 :page => params[:page],
29 format.html {} 30 :per_page => 23
31 )
32
33 respond_to do |format|
34 format.html {}
35 end
36 else
37 respond_to do |format|
38 format.html { head :bad_request }
39 end
30 end 40 end
41
31 end 42 end
32 43
33end 44end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 87df678..98fd534 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -2,24 +2,24 @@ class UsersController < ApplicationController
2 2
3 # Private 3 # Private
4 4
5 before_filter :login_required 5 before_action :login_required
6 before_filter :find_user, :only => [:show, :edit, :update, :destroy] 6 before_action :find_user, :only => [:show, :edit, :update, :destroy]
7 before_filter :verify_status, :except => [:index, :show] 7 before_action :verify_status, :except => [:index, :show]
8 8
9 layout 'admin' 9 layout 'admin'
10 10
11 def index 11 def index
12 @users = User.all(:order => "login ASC").group_by do |user| 12 @users = User.order("login ASC").all.group_by do |user|
13 user.admin? ? :admin : :user 13 user.admin? ? :admin : :user
14 end 14 end
15 end 15 end
16 16
17 def new 17 def new
18 @user = User.new( params[:user] ) 18 @user = User.new
19 end 19 end
20 20
21 def create 21 def create
22 @user = User.new params[:user] 22 @user = User.new user_params
23 23
24 if @user.save 24 if @user.save
25 flash[:notice] = "User created #{@user.login}" 25 flash[:notice] = "User created #{@user.login}"
@@ -33,8 +33,10 @@ class UsersController < ApplicationController
33 end 33 end
34 34
35 def update 35 def update
36 params[:user].delete(:admin) unless current_user.is_admin? 36 permitted = user_params
37 if @user.update_attributes(params[:user]) 37 permitted.delete(:admin) unless current_user.is_admin?
38
39 if @user.update(permitted)
38 flash[:notice] = "Updated user #{@user.login}" 40 flash[:notice] = "Updated user #{@user.login}"
39 redirect_to user_path(@user) 41 redirect_to user_path(@user)
40 else 42 else
@@ -51,6 +53,11 @@ class UsersController < ApplicationController
51 end 53 end
52 54
53 private 55 private
56
57 def user_params
58 params.fetch(:user, {}).permit(:login, :email, :password, :password_confirmation, :admin)
59 end
60
54 def find_user 61 def find_user
55 @user = User.find(params[:id]) 62 @user = User.find(params[:id])
56 end 63 end
diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb
index da8945e..e5c3d5c 100644
--- a/app/helpers/admin_helper.rb
+++ b/app/helpers/admin_helper.rb
@@ -1,11 +1,11 @@
1module AdminHelper 1module AdminHelper
2 2
3 def language_selector 3 def language_selector
4 case I18n.locale 4 case I18n.locale
5 when :de 5 when :de
6 link_to 'English', url_for(:overwrite_params => {:locale => :en}) 6 link_to raw('<span class="inactive">English</span>'), url_for(params.permit!.to_h.merge('locale' => 'en'))
7 when :en 7 when :en
8 link_to 'Deutsch', url_for(:overwrite_params => {:locale => :de}) 8 link_to raw('<span class="inactive">Deutsch</span>'), url_for(params.permit!.to_h.merge('locale' => 'de'))
9 end 9 end
10 end 10 end
11end \ No newline at end of file 11end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 22a7940..0be66e9 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,3 +1,14 @@
1# Methods added to this helper will be available to all templates in the application. 1# Methods added to this helper will be available to all templates in the application.
2module ApplicationHelper 2module ApplicationHelper
3 def form_error_messages(form_object)
4 object = form_object.is_a?(ActionView::Helpers::FormBuilder) ? form_object.object : form_object
5 return "" unless object && object.errors.any?
6 content_tag(:div, :class => "error_messages") do
7 content_tag(:ul) do
8 object.errors.full_messages.map do |msg|
9 content_tag(:li, msg)
10 end.join.html_safe
11 end
12 end
13 end
3end 14end
diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb
index d6c96f1..21cc579 100644
--- a/app/helpers/content_helper.rb
+++ b/app/helpers/content_helper.rb
@@ -1,7 +1,7 @@
1module ContentHelper 1module ContentHelper
2 2
3 def main_menu 3 def main_menu
4 menu_items = MenuItem.all(:order => "position ASC") 4 menu_items = MenuItem.order("position ASC").all
5 render( 5 render(
6 :partial => 'content/main_navigation', 6 :partial => 'content/main_navigation',
7 :locals => {:menu_items => menu_items} 7 :locals => {:menu_items => menu_items}
@@ -9,13 +9,13 @@ module ContentHelper
9 end 9 end
10 10
11 def calendar 11 def calendar
12 occurrences = Occurrence.find_in_range(Time.now, (Time.now+14.days)) 12 occurrences = Occurrence.find_in_range(Time.now, (Time.now+6.weeks))
13 13
14 if occurrences.empty? 14 if occurrences.empty?
15 occurrences = Occurrence.find_next 15 occurrences = Occurrence.find_next
16 end 16 end
17 17
18 occurrences = occurrences.reject { |o| o.node.head.nil? } 18 occurrences = occurrences.reject { |o| o.node.nil? || o.node.head.nil? }
19 19
20 render( 20 render(
21 :partial => 'content/front_page_calendar', 21 :partial => 'content/front_page_calendar',
@@ -43,7 +43,7 @@ module ContentHelper
43 # Returns the published_at attribute of a page if it is not nil, otherwise 43 # Returns the published_at attribute of a page if it is not nil, otherwise
44 # it returns the auto-filled value of the created_at attribute 44 # it returns the auto-filled value of the created_at attribute
45 def date_for_page page 45 def date_for_page page
46 page.published_at.to_s(:db) rescue page.created_at.to_s(:db) 46 I18n.l(page.published_at, :format => :ccc) rescue I18n.l(page.created_at, :format => :ccc)
47 end 47 end
48 48
49 def author_for_page page 49 def author_for_page page
@@ -51,7 +51,7 @@ module ContentHelper
51 end 51 end
52 52
53 def page_title 53 def page_title
54 if @page.title && @page.title != "" 54 if @page && @page.title && @page.title != ""
55 "CCC | #{@page.title}" 55 "CCC | #{@page.title}"
56 else 56 else
57 "CCC | Chaos Computer Club" 57 "CCC | Chaos Computer Club"
@@ -59,41 +59,43 @@ module ContentHelper
59 end 59 end
60 60
61 # This method is an output filter for templates. It accepts any kind of text 61 # This method is an output filter for templates. It accepts any kind of text
62 # and checks for an <aggregate /> tag within it. If such a tag is found, its 62 # and checks for an [aggregate short code within it. If such a code is found,
63 # attributes are parsed and converted into parameters for the 63 # its # attributes are parsed and converted into parameters for the
64 # render_collection method. The <aggregate /> tag will then be replaced 64 # render_collection method. The [aggregate ] short code will then be replaced
65 # entirely with the output of the render_collection method. 65 # entirely with the output of the render_collection method.
66 # 66 #
67 # Syntax of the <aggregate /> tag: 67 # Syntax of the [aggregate ] short code:
68 # 68 #
69 # <aggregate 69 # [aggregate
70 # flags="update, pressemitteilung" 70 # flags="update, pressemitteilung"
71 # limit="20" 71 # limit="20"
72 # order_by="published_at" 72 # order_by="published_at"
73 # order_direction="DESC" 73 # order_direction="DESC"
74 # /> 74 # ]
75 def aggregate? content 75 def aggregate? content
76 options = {} 76 options = {}
77 77
78 cccms_attributes = ActionView::Base.sanitized_allowed_attributes + ['lang']
79
78 begin 80 begin
79 if content =~ /<aggregate([^<>]*)>/ 81 if content =~ /\[aggregate([^\]]*)\]/
80 tag = $~.to_s 82 tag = $~.to_s
81 matched_data = $1.scan(/\w+\=\"[a-zA-Z\s\/_\d,]*\"/) 83 matched_data = $1.scan(/\w+\="[a-zA-Z\s\/_\d,.=]*"/)
82 84
83 matched_data.each do |data| 85 matched_data.each do |data|
84 splitted_data = data.split("=") 86 splitted_data = data.split("=", 2)
85 options[splitted_data[0].to_sym] = splitted_data[1].gsub(/\"/, "") 87 options[splitted_data[0].to_sym] = splitted_data[1].gsub(/"/, "")
86 end 88 end
87 89
88 options[:partial] = select_partial( options[:partial] ) 90 options[:partial] = select_partial(options[:partial])
89 91
90 sanitize( content.sub(tag, render_collection(options)) ) 92 sanitize(content.sub(tag, render_collection(options)), :attributes => cccms_attributes)
91 else 93 else
92 sanitize( content ) 94 sanitize(content, :attributes => cccms_attributes)
93 end 95 end
94 96
95 rescue 97 rescue
96 sanitize( content ) 98 sanitize(content, :attributes => cccms_attributes)
97 end 99 end
98 end 100 end
99 101
@@ -124,9 +126,7 @@ module ContentHelper
124 # Check if a custom partial exists in the proper location 126 # Check if a custom partial exists in the proper location
125 def partial_exists? partial 127 def partial_exists? partial
126 File.exist?( 128 File.exist?(
127 File.join( 129 Rails.root.join('app', 'views', 'custom', 'partials', "_#{partial}.html.erb")
128 RAILS_ROOT, 'app', 'views', 'custom', 'partials', "_#{partial}.html.erb"
129 )
130 ) 130 )
131 end 131 end
132 132
diff --git a/app/helpers/link_helper.rb b/app/helpers/link_helper.rb
index 1b20e6d..878e8e4 100644
--- a/app/helpers/link_helper.rb
+++ b/app/helpers/link_helper.rb
@@ -1,54 +1,62 @@
1module LinkHelper 1module LinkHelper
2 2
3 def content_path_helper path_array 3 def content_path_helper path_array
4 url_for( 4 url_for(
5 :controller => :content, 5 :controller => :content,
6 :action => :render_page, 6 :action => :render_page,
7 :locale => params[:locale] || I18n.locale, 7 :locale => (params[:locale] || I18n.locale).to_sym == I18n.default_locale ? nil : (params[:locale] || I18n.locale),
8 :page_path => path_array 8 :page_path => path_array
9 ) 9 )
10 end 10 end
11 11
12 def content_url_helper path_array 12 def content_url_helper path_array
13 request.protocol + request.host_with_port + content_path_helper(path_array) 13 request.protocol + request.host_with_port + content_path_helper(path_array)
14 end 14 end
15 15
16 def link_to_path title, path, html_options = {} 16 def link_to_path title, path, html_options = {}
17 return "" if path.nil?
18
17 if params[:page_path] 19 if params[:page_path]
18 active = (params[:page_path].join("/") == path.sub(/^\//, "")) 20 page_path = params[:page_path].is_a?(Array) ? params[:page_path].join("/") : params[:page_path]
21 active = (page_path == path.sub(/^\//, ""))
19 end 22 end
20 23
21 active_class = active ? {:class => 'active'} : {:class => 'inactive'} 24 active_class = active ? {:class => 'active'} : {:class => 'inactive'}
22
23 html_options = html_options.merge(active_class) 25 html_options = html_options.merge(active_class)
24 26 locale = (params[:locale] || I18n.locale).to_sym == I18n.default_locale ? nil : (params[:locale] || I18n.locale)
25 params[:locale] ||= I18n.locale 27
26 28 link_to(
27 link_to( 29 title,
28 title, { 30 content_path(path.sub(/^\//, ""), :locale => locale),
29 :controller => :content,
30 :action => :render_page,
31 :locale => params[:locale],
32 :page_path => (path.sub(/^\//, "").split("/") rescue "")
33 },
34 html_options 31 html_options
35 ) 32 )
36 end 33 end
37 34
38 def selected? controller_name 35 def selected? controller_name
39 if params[:controller] == controller_name 36 if params[:controller] == controller_name
40 return :class => "selected" 37 return :class => "selected"
41 end 38 end
42 end 39 end
43 40
44 def unlock_link 41 def unlock_link
45 message = "Are you sure you want to unlock?\n" + 42 message = "Are you sure you want to unlock?\n" \
46 "Locked by #{@node.lock_owner.login}\n" + 43 "Locked by #{@node.lock_owner.login}\n" \
47 "Last modified #{@page.updated_at.to_s(:db)}" 44 "Last modified #{@page.updated_at.to_fs(:db)}"
48 45 button_to 'Unlock', unlock_node_path(@node),
49 link_to( 46 method: :put,
50 'Unlock', unlock_node_path(@node), :method => :put, :confirm => message 47 form: { data: { confirm: message } }
48 end
49
50 def content_path(page_path = nil, options = {})
51 if page_path.is_a?(Hash)
52 options = page_path
53 page_path = options.delete(:page_path)
54 end
55 locale = options[:locale] || params[:locale] || I18n.locale
56 options[:locale] = (locale.to_sym == I18n.default_locale) ? nil : locale
57 Rails.application.routes.url_helpers.content_path(
58 Array(page_path).join("/").sub(/^\//, ""),
59 options
51 ) 60 )
52 end 61 end
53 62end
54end \ No newline at end of file
diff --git a/app/helpers/nodes_helper.rb b/app/helpers/nodes_helper.rb
index d889719..a054a2e 100644
--- a/app/helpers/nodes_helper.rb
+++ b/app/helpers/nodes_helper.rb
@@ -4,6 +4,10 @@ module NodesHelper
4 if node.head 4 if node.head
5 node.head.title 5 node.head.title
6 else 6 else
7 if not node.draft or not node.draft.title
8 logger.error "Missing title in node #{node.id}"
9 return "NO TITLE"
10 end
7 node.draft.title 11 node.draft.title
8 end 12 end
9 end 13 end
@@ -24,14 +28,20 @@ module NodesHelper
24 def user_list 28 def user_list
25 User.all.map {|u| [u.login, u.id]} 29 User.all.map {|u| [u.login, u.id]}
26 end 30 end
27 31
28 def event_information 32 def event_information
29 if @node.event 33 if @node.event
30 "#{@node.event.start_time.to_s(:db)} - #{@node.event.end_time.to_s(:db)} > " \ 34 safe_join([
31 "#{link_to 'show', event_path(@node.event)} " \ 35 "#{@node.event.start_time.to_fs(:db)} - #{@node.event.end_time.to_fs(:db)} > ",
32 "#{link_to 'edit', edit_event_path(@node.event)}" 36 link_to('show', event_path(@node.event)),
37 ' ',
38 link_to('edit', edit_event_path(@node.event))
39 ])
33 else 40 else
34 "no event attached > #{link_to 'add', new_event_path(:node_id => @node.id)}" 41 safe_join([
42 'no event attached > ',
43 link_to('add', new_event_path(:node_id => @node.id))
44 ])
35 end 45 end
36 end 46 end
37end 47end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 0000000..10a4cba
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
1class ApplicationRecord < ActiveRecord::Base
2 self.abstract_class = true
3end
diff --git a/app/models/asset.rb b/app/models/asset.rb
index 5bfea76..aca0ee8 100644
--- a/app/models/asset.rb
+++ b/app/models/asset.rb
@@ -1,39 +1,12 @@
1class Asset < ActiveRecord::Base 1class Asset < ApplicationRecord
2
3 include FileAttachment
2 4
3 has_many :related_assets, :dependent => :destroy 5 has_many :related_assets, :dependent => :destroy
4 has_many :pages, :through => :related_assets 6 has_many :pages, :through => :related_assets
5 7
6 has_attached_file( 8 scope :images, -> { where(:upload_content_type => ["image/gif", "image/jpeg", "image/png", "image/webp"]) }
7 :upload, 9 scope :documents, -> { where(:upload_content_type => ["application/pdf", "text/plain", "text/rtf"]) }
8 :styles => { 10 scope :audio, -> { where(:upload_content_type => ["audio/mpeg", "audio/x-m4a", "audio/wav", "audio/x-wav"]) }
9 :medium => "300x300", 11
10 :thumb => "100x100",
11 :headline => "460x250#"
12 }
13 )
14
15 named_scope :images, :conditions => {
16 :upload_content_type => [
17 "image/gif",
18 "image/jpeg",
19 "image/png"
20 ]
21 }
22
23 named_scope :documents, :conditions => {
24 :upload_content_type => [
25 "application/pdf",
26 "text/plain",
27 "text/rtf"
28 ]
29 }
30
31 named_scope :audio, :conditions => {
32 :upload_content_type => [
33 "audio/mpeg",
34 "audio/x-m4a",
35 "audio/wav",
36 "audio/x-wav"
37 ]
38 }
39end 12end
diff --git a/app/models/concerns/file_attachment.rb b/app/models/concerns/file_attachment.rb
new file mode 100644
index 0000000..0e99fa2
--- /dev/null
+++ b/app/models/concerns/file_attachment.rb
@@ -0,0 +1,139 @@
1# FileAttachment — minimal drop-in replacement for Paperclip's has_attached_file.
2#
3# Provides the same interface used throughout this codebase:
4# asset.upload.url -> "/system/uploads/:id/original/:filename"
5# asset.upload.url(:thumb) -> "/system/uploads/:id/thumb/:filename"
6# asset.upload.content_type -> string
7# asset.upload.size -> integer (bytes)
8#
9# Files are stored at:
10# Rails.root/public/system/uploads/:id/:style/:filename
11#
12# Image variants are generated via ImageMagick (convert) on upload.
13# Non-image files get only an original, no variants.
14#
15# To replace an asset: assign a new file to asset.upload= and save.
16# The filename is fixed on first upload and preserved on replacement,
17# keeping all public URLs stable.
18#
19# Future: if more sophisticated asset management is needed (versioning,
20# S3, on-demand resizing), replace this module and keep the interface.
21
22module FileAttachment
23 extend ActiveSupport::Concern
24
25 STYLES = {
26 medium: { geometry: "300x300>", format: nil },
27 thumb: { geometry: "100x100>", format: nil },
28 headline: { geometry: "460x250!", format: nil }
29 }.freeze
30
31 IMAGE_CONTENT_TYPES = %w[image/jpeg image/gif image/png image/webp].freeze
32 VECTOR_CONTENT_TYPES = %w[image/svg+xml].freeze
33 DISPLAYABLE_AS_IMAGE = IMAGE_CONTENT_TYPES + VECTOR_CONTENT_TYPES
34
35 included do
36 attr_reader :upload
37
38 after_initialize :build_upload_proxy
39 after_save :process_upload
40 before_destroy :delete_upload_files
41 end
42
43 def upload=(uploaded_file)
44 return if uploaded_file.blank?
45 @pending_upload = uploaded_file
46 # Populate the database columns immediately so validations can use them
47 self.upload_file_name = sanitize_filename(uploaded_file.original_filename)
48 self.upload_content_type = uploaded_file.content_type.to_s.split(';').first.strip
49 self.upload_file_size = uploaded_file.size
50 self.upload_updated_at = Time.current
51 build_upload_proxy
52 end
53
54 private
55
56 def build_upload_proxy
57 @upload = UploadProxy.new(self)
58 end
59
60 def process_upload
61 return unless @pending_upload
62 uploaded_file = @pending_upload
63 @pending_upload = nil
64
65 old_dir = Rails.root.join("public", "system", "uploads", id.to_s)
66 FileUtils.rm_rf(old_dir) if Dir.exist?(old_dir)
67
68 original_path = file_path(:original)
69 FileUtils.mkdir_p(File.dirname(original_path))
70 FileUtils.cp(uploaded_file.tempfile.path, original_path)
71
72 if IMAGE_CONTENT_TYPES.include?(upload_content_type)
73 generate_variants(original_path)
74 elsif VECTOR_CONTENT_TYPES.include?(upload_content_type)
75 generate_svg_variants(original_path)
76 end
77 end
78
79 def generate_variants(original_path)
80 STYLES.each do |style, options|
81 dest_path = file_path(style)
82 FileUtils.mkdir_p(File.dirname(dest_path))
83 system("magick", original_path, "-resize", options[:geometry], dest_path)
84 end
85 end
86
87 def generate_svg_variants(original_path)
88 STYLES.each do |style, _|
89 dest_path = file_path(style)
90 FileUtils.mkdir_p(File.dirname(dest_path))
91 FileUtils.cp(original_path, dest_path)
92 end
93 end
94
95 def delete_upload_files
96 dir = Rails.root.join("public", "system", "uploads", id.to_s)
97 FileUtils.rm_rf(dir) if Dir.exist?(dir)
98 end
99
100 def file_path(style)
101 Rails.root.join(
102 "public", "system", "uploads",
103 id.to_s, style.to_s, upload_file_name
104 ).to_s
105 end
106
107 def sanitize_filename(filename)
108 File.basename(filename).gsub(/[^\w\.\-]/, '_')
109 end
110
111 # Proxy object returned by asset.upload, providing the Paperclip-compatible
112 # interface used in views: .url, .url(:style), .content_type, .size
113 class UploadProxy
114 def initialize(record)
115 @record = record
116 end
117
118 def url(style = :original)
119 return "" if @record.upload_file_name.blank?
120 "/system/uploads/#{@record.id}/#{style}/#{@record.upload_file_name}"
121 end
122
123 def content_type
124 @record.upload_content_type.to_s
125 end
126
127 def size
128 @record.upload_file_size.to_i
129 end
130
131 def present?
132 @record.upload_file_name.present?
133 end
134
135 def blank?
136 !present?
137 end
138 end
139end
diff --git a/app/models/event.rb b/app/models/event.rb
index 60b8521..94a22e3 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -1,4 +1,4 @@
1class Event < ActiveRecord::Base 1class Event < ApplicationRecord
2 2
3 # Associations 3 # Associations
4 4
@@ -12,14 +12,12 @@ class Event < ActiveRecord::Base
12 # Instance Methods 12 # Instance Methods
13 13
14 def occurrences_in_range start_time, end_time 14 def occurrences_in_range start_time, end_time
15 self.occurrences.find( 15 self.occurrences.where(
16 :all, :conditions => [ 16 "start_time > ? AND end_time < ?",
17 "start_time > ? AND end_time < ?", 17 start_time, end_time
18 start_time, end_time
19 ]
20 ) 18 )
21 end 19 end
22 20
23 private 21 private
24 def generate_occurences 22 def generate_occurences
25 Occurrence.generate self 23 Occurrence.generate self
diff --git a/app/models/locked_by_another_user.rb b/app/models/locked_by_another_user.rb
new file mode 100644
index 0000000..6f9e272
--- /dev/null
+++ b/app/models/locked_by_another_user.rb
@@ -0,0 +1 @@
class LockedByAnotherUser < StandardError; end
diff --git a/app/models/menu_item.rb b/app/models/menu_item.rb
index 054e7ee..7769b7f 100644
--- a/app/models/menu_item.rb
+++ b/app/models/menu_item.rb
@@ -1,6 +1,6 @@
1class MenuItem < ActiveRecord::Base 1class MenuItem < ApplicationRecord
2 2
3 default_scope :conditions => {:type => "MenuItem"} 3 default_scope -> { where(:type => "MenuItem") }
4 4
5 translates :title 5 translates :title
6 6
@@ -24,5 +24,5 @@ end
24 24
25 25
26class FeaturedArticle < MenuItem 26class FeaturedArticle < MenuItem
27 default_scope :conditions => {:type => "FeaturedArticle"} 27 default_scope -> { where(:type => "FeaturedArticle") }
28end \ No newline at end of file 28end
diff --git a/app/models/node.rb b/app/models/node.rb
index 6c11fed..92ecc12 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -1,14 +1,14 @@
1class Node < ActiveRecord::Base 1class Node < ApplicationRecord
2 # Mixins and Plugins 2 # Mixins and Plugins
3 acts_as_nested_set 3 acts_as_nested_set
4 4
5 # Associations 5 # Associations
6 has_many :pages, :order => "revision ASC" 6 has_many :pages, -> { order("revision ASC") }, :dependent => :destroy
7 belongs_to :head, :class_name => "Page", :foreign_key => :head_id 7 belongs_to :head, :class_name => "Page", :foreign_key => :head_id, :dependent => :destroy, optional: true
8 belongs_to :draft, :class_name => "Page", :foreign_key => :draft_id 8 belongs_to :draft, :class_name => "Page", :foreign_key => :draft_id, :dependent => :destroy, optional: true
9 has_many :permissions 9 has_many :permissions, :dependent => :destroy
10 has_one :event 10 has_one :event, :dependent => :destroy
11 belongs_to :lock_owner, :class_name => "User", :foreign_key => :locking_user_id 11 belongs_to :lock_owner, :class_name => "User", :foreign_key => :locking_user_id, optional: true
12 12
13 # Callbacks 13 # Callbacks
14 after_create :initialize_empty_page 14 after_create :initialize_empty_page
@@ -16,20 +16,20 @@ class Node < ActiveRecord::Base
16 after_save :update_unique_names_of_children 16 after_save :update_unique_names_of_children
17 17
18 # Validations 18 # Validations
19 validates_length_of :slug, :within => 1..255, :unless => "parent_id.nil?" 19 validates_length_of :slug, :within => 1..255, :unless => -> { parent_id.nil? }
20 validates_presence_of :slug, :unless => "parent_id.nil?" 20 validates_presence_of :slug, :unless => -> { parent_id.nil? }
21 validates_uniqueness_of :slug, :scope => :parent_id, :unless => "parent_id.nil?" 21 validates_uniqueness_of :slug, :scope => :parent_id, :unless => -> { parent_id.nil? }
22 validates_presence_of :parent_id, :unless => "Node.root.nil?" 22 validates_presence_of :parent_id, :unless => -> { Node.root.nil? }
23 23
24 validate :borders # This should never ever happen. 24 validate :borders # This should never ever happen.
25 25
26 # Index for Fulltext Search 26 # Index for Fulltext Search
27 define_index do 27 # define_index do
28 indexes head.translations.title 28 # indexes head.translations.title
29 indexes slug 29 # indexes slug
30 indexes unique_name 30 # indexes unique_name
31 indexes head.translations.body 31 # indexes head.translations.body
32 end 32 # end
33 33
34 # Class methods 34 # Class methods
35 35
@@ -39,8 +39,8 @@ class Node < ActiveRecord::Base
39 # revision with -1. It raises an Argument error if the revision is not a 39 # revision with -1. It raises an Argument error if the revision is not a
40 # Fixnum 40 # Fixnum
41 def self.find_page path, revision = -1 41 def self.find_page path, revision = -1
42 unless revision.class == Fixnum 42 unless revision.is_a?(Integer)
43 raise ArgumentError, "revision must be a Fixnum" 43 raise ArgumentError, "revision must be a Integer"
44 end 44 end
45 45
46 node = Node.find_by_unique_name(path) 46 node = Node.find_by_unique_name(path)
@@ -60,6 +60,7 @@ class Node < ActiveRecord::Base
60 # Instance Methods 60 # Instance Methods
61 61
62 def find_or_create_draft current_user 62 def find_or_create_draft current_user
63 self.wipe_draft!
63 if draft && self.lock_owner == current_user 64 if draft && self.lock_owner == current_user
64 draft 65 draft
65 elsif draft && self.lock_owner.nil? 66 elsif draft && self.lock_owner.nil?
@@ -72,7 +73,7 @@ class Node < ActiveRecord::Base
72 raise( 73 raise(
73 LockedByAnotherUser, 74 LockedByAnotherUser,
74 "Page is locked by another user who is working on it! " \ 75 "Page is locked by another user who is working on it! " \
75 "Last modification: #{draft.updated_at.to_s(:db)}" 76 "Last modification: #{draft.updated_at.to_fs(:db)}"
76 ) 77 )
77 else 78 else
78 lock_for! current_user 79 lock_for! current_user
@@ -94,25 +95,55 @@ class Node < ActiveRecord::Base
94 end 95 end
95 96
96 def publish_draft! 97 def publish_draft!
98 # Return nil if nothing to publish and no staged changes
99 return nil unless self.draft || staged_slug || staged_parent_id
100
97 if self.draft 101 if self.draft
98 self.head = self.draft 102 self.head = self.draft
99 self.head.published_at ||= Time.now 103 self.head.published_at ||= Time.now
100 self.head.save! 104 self.head.save!
101
102 self.draft = nil 105 self.draft = nil
106 end
103 107
104 if staged_slug && (staged_slug != slug) 108 if staged_slug && (staged_slug != slug)
105 self.slug = staged_slug 109 self.slug = staged_slug
106 end 110 self.staged_slug = nil
111 end
107 112
108 if staged_parent_id && (staged_parent_id != parent_id) 113 if staged_parent_id && (staged_parent_id != parent_id)
109 self.parent_id = staged_parent_id 114 new_parent = Node.find(staged_parent_id)
115 self.staged_parent_id = nil
116 self.save!
117 self.move_to_child_of(new_parent)
118 else
119 unless self.save
120 raise ActiveRecord::RecordInvalid.new(self)
110 end 121 end
122 end
111 123
112 self.save! 124 self.reload
125 self.update_unique_name
126 self.send(:update_unique_names_of_children)
127 self.unlock!
128 self
129 end
130
131 # removes a draft and the lock if it is older than a day and still
132 # identical to head
133 def wipe_draft!
134 unless self.draft
113 self.unlock! 135 self.unlock!
114 self 136 return
115 end 137 end
138 return unless self.head
139 return unless self.draft.updated_at < 1.day.ago
140 return if self.head.has_changes_to? self.draft
141
142 self.draft.destroy
143 self.draft_id = nil
144 self.unlock!
145 self.save!
146 self.reload
116 end 147 end
117 148
118 def restore_revision! revision 149 def restore_revision! revision
@@ -126,7 +157,7 @@ class Node < ActiveRecord::Base
126 157
127 # returns an array with all parts of a unique_name rather than a string 158 # returns an array with all parts of a unique_name rather than a string
128 def unique_path 159 def unique_path
129 unique_name.split("/") rescue [unique_name] 160 unique_name.to_s.split("/")
130 end 161 end
131 162
132 # returns array with pages up to root excluding root 163 # returns array with pages up to root excluding root
@@ -180,6 +211,15 @@ class Node < ActiveRecord::Base
180 self.created_at < new_id_format_date ? unique_path : id 211 self.created_at < new_id_format_date ? unique_path : id
181 end 212 end
182 213
214 # Full-text search across all locale translations using PostgreSQL tsvector.
215 # Uses 'simple' dictionary (no stemming, no stopwords) so queries work
216 # across German and English content without language detection.
217 def self.search(term, _ = {})
218 joins(head: :translations)
219 .where("page_translations.search_vector @@ plainto_tsquery('simple', ?)", term)
220 .distinct
221 end
222
183 protected 223 protected
184 def lock_for! current_user 224 def lock_for! current_user
185 self.lock_owner = current_user 225 self.lock_owner = current_user
@@ -208,8 +248,12 @@ class Node < ActiveRecord::Base
208 # Hopefully until no childrens occur 248 # Hopefully until no childrens occur
209 def update_unique_names_of_children 249 def update_unique_names_of_children
210 unless root? 250 unless root?
211 self.descendants.each do |descendant| 251 # Use parent_id-based traversal instead of lft/rgt descendants
212 descendant.update_unique_name 252 # due to awesome_nested_set not refreshing parent lft/rgt in memory
253 Node.where(:parent_id => self.id).each do |child|
254 child.reload
255 child.update_unique_name
256 child.send(:update_unique_names_of_children)
213 end 257 end
214 end 258 end
215 end 259 end
@@ -220,7 +264,3 @@ class Node < ActiveRecord::Base
220 end 264 end
221 end 265 end
222end 266end
223
224class LockedByAnotherUser < StandardError; end
225
226
diff --git a/app/models/occurrence.rb b/app/models/occurrence.rb
index 591e1e0..3baf447 100644
--- a/app/models/occurrence.rb
+++ b/app/models/occurrence.rb
@@ -1,7 +1,7 @@
1# TODO Make a gem out of the c wrapper 1# TODO Make a gem out of the c wrapper
2require 'chaos_calendar' 2require 'chaos_calendar'
3 3
4class Occurrence < ActiveRecord::Base 4class Occurrence < ApplicationRecord
5 5
6 # Associations 6 # Associations
7 7
@@ -11,29 +11,22 @@ class Occurrence < ActiveRecord::Base
11 # Class Methods 11 # Class Methods
12 12
13 def self.find_in_range start_time, end_time 13 def self.find_in_range start_time, end_time
14 find( 14 includes(:node)
15 :all, 15 .where("start_time > ? AND end_time < ?", start_time, end_time)
16 :include => :node, 16 .order("start_time")
17 :conditions => [
18 "start_time > ? AND end_time < ?", start_time, end_time
19 ]
20 )
21 end 17 end
22 18
23 def self.find_next 19 def self.find_next
24 find( 20 includes(:node)
25 :all, 21 .where("start_time > ?", Time.now)
26 :limit => 1, 22 .limit(1)
27 :include => :node,
28 :conditions => ["start_time > ?", Time.now]
29 )
30 end 23 end
31 24
32 # Deletes all Occurrences which belong to the given event. Afterwards a few 25 # Deletes all Occurrences which belong to the given event. Afterwards a few
33 # variables are set to save repetitive queries. The occurrences of the given 26 # variables are set to save repetitive queries. The occurrences of the given
34 # event are then calculated and created. 27 # event are then calculated and created.
35 def self.generate event 28 def self.generate event
36 self.delete_all(:event_id => event.id) 29 self.where(:event_id => event.id).delete_all
37 30
38 node = event.node 31 node = event.node
39 duration = (event.end_time - event.start_time) 32 duration = (event.end_time - event.start_time)
diff --git a/app/models/page.rb b/app/models/page.rb
index c5da386..e6baf20 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -1,25 +1,9 @@
1require 'xml' 1require 'xml'
2 2
3class Page < ActiveRecord::Base 3class Page < ApplicationRecord
4 4
5 PUBLIC_TEMPLATE_PATH = File.join(%w(custom page_templates public)) 5 PUBLIC_TEMPLATE_PATH = File.join(%w(custom page_templates public))
6 FULL_PUBLIC_TEMPLATE_PATH = File.join(RAILS_ROOT, 'app', 'views', PUBLIC_TEMPLATE_PATH) 6 FULL_PUBLIC_TEMPLATE_PATH = Rails.root.join('app', 'views', PUBLIC_TEMPLATE_PATH)
7
8 # named scopes
9
10 named_scope(
11 :drafts,
12 :joins => :node,
13 :include => [:translations],
14 :conditions => ["nodes.draft_id = pages.id"]
15 )
16
17 named_scope(
18 :heads,
19 :joins => :node,
20 :include => [:translations],
21 :conditions => ["nodes.head_id = pages.id"]
22 )
23 7
24 # Mixins and Plugins 8 # Mixins and Plugins
25 acts_as_taggable 9 acts_as_taggable
@@ -28,20 +12,21 @@ class Page < ActiveRecord::Base
28 translates :title, :abstract, :body # Globalize2 12 translates :title, :abstract, :body # Globalize2
29 13
30 # Associations 14 # Associations
31 belongs_to :node 15 belongs_to :node, optional: true
32 belongs_to :user 16 belongs_to :user, optional: true
33 belongs_to :editor, :class_name => "User" 17 belongs_to :editor, :class_name => "User", optional: true
34 has_many :related_assets 18 has_many :related_assets
35 has_many :assets, :through => :related_assets, :order => "position ASC" 19 has_many :assets, -> { order("position ASC") }, :through => :related_assets
20
21 # Named scopes
22 scope :drafts, -> { joins(:node).includes(:translations).where("nodes.draft_id = pages.id") }
23 scope :heads, -> { joins(:node).includes(:translations).where("nodes.head_id = pages.id") }
36 24
37 # Filter 25 # Filter
38 before_create :set_page_title 26 before_create :set_page_title
39 before_create :set_template 27 before_create :set_template
40 before_save :rewrite_links_in_body 28 before_save :rewrite_links_in_body
41 29
42 # Security
43 attr_accessible :title, :abstract, :body, :template_name, :published_at, :user_id
44
45 # Class Methods 30 # Class Methods
46 31
47 # This method is most likely called from the ContentHelper.render_collection 32 # This method is most likely called from the ContentHelper.render_collection
@@ -51,8 +36,8 @@ class Page < ActiveRecord::Base
51 # partially or entirely overwritten by the options hash. Afterwards the merged 36 # partially or entirely overwritten by the options hash. Afterwards the merged
52 # parameters are used to query the DB for Pages matching these parameters. 37 # parameters are used to query the DB for Pages matching these parameters.
53 # The aggregation only takes published pages into account. 38 # The aggregation only takes published pages into account.
54 def self.aggregate options, page=1
55 39
40 def self.aggregate options, page=1
56 defaults = { 41 defaults = {
57 :tags => "", 42 :tags => "",
58 :limit => 25, 43 :limit => 25,
@@ -62,15 +47,24 @@ class Page < ActiveRecord::Base
62 47
63 options = defaults.merge options 48 options = defaults.merge options
64 49
65 Page.heads.paginate( 50 scope = Page.heads
66 find_options_for_find_tagged_with( 51 unless options[:tags].blank?
67 options[:tags].gsub(/\s/, ","), :match_all => true 52 tag_names = options[:tags].gsub(/\s/, ",").split(",").map(&:strip).map(&:downcase).uniq.reject(&:blank?)
68 ).merge( 53
69 :page => page, 54 unless tag_names.empty?
70 :per_page => options[:limit], 55 scope = scope
71 :order => "#{options[:order_by]} #{options[:order_direction]}" 56 .joins("JOIN taggings ON taggings.taggable_id = pages.id
72 ) 57 AND taggings.taggable_type = 'Page'
73 ) 58 AND taggings.context = 'tags'")
59 .joins("JOIN tags ON tags.id = taggings.tag_id")
60 .where("LOWER(tags.name) IN (?)", tag_names)
61 .group("pages.id")
62 .having("COUNT(DISTINCT tags.id) = ?", tag_names.length)
63 end
64 end
65
66 scope.order("#{options[:order_by]} #{options[:order_direction]}")
67 .paginate(:page => page, :per_page => options[:limit])
74 end 68 end
75 69
76 def self.custom_templates 70 def self.custom_templates
@@ -89,11 +83,24 @@ class Page < ActiveRecord::Base
89 # outdated_translations? for more information. 83 # outdated_translations? for more information.
90 # Takes :locale => <locale> and :delta_time => 12.hours as options 84 # Takes :locale => <locale> and :delta_time => 12.hours as options
91 def self.find_with_outdated_translations options = {} 85 def self.find_with_outdated_translations options = {}
92 Page.all(:include => :translations).select do |page| 86 Page.includes(:translations).select do |page|
93 page.outdated_translations? options 87 page.outdated_translations? options
94 end 88 end
95 end 89 end
96 90
91 # Is used to compare a node's head with the node's draft
92
93 def has_changes_to? draft
94 return true unless node == draft.node
95 return true unless assets == draft.assets
96 return true unless tag_list == draft.tag_list
97 return true unless template_name == draft.template_name
98 return true unless translated_locales.sort_by(&:to_s) == draft.translated_locales.sort_by(&:to_s)
99 changed = false
100 translated_locales.each { |locale| I18n.with_locale(locale) { changed = true unless title == draft.title && abstract == draft.abstract && body == draft.body } }
101 return changed
102 end
103
97 # Instance Methods 104 # Instance Methods
98 105
99 def public_template_path 106 def public_template_path
@@ -105,7 +112,7 @@ class Page < ActiveRecord::Base
105 end 112 end
106 113
107 def template_exists? 114 def template_exists?
108 File.exists? "#{full_public_template_path}.html.erb" 115 File.exist? "#{full_public_template_path}.html.erb"
109 end 116 end
110 117
111 def valid_template 118 def valid_template
@@ -136,7 +143,7 @@ class Page < ActiveRecord::Base
136 143
137 # Clone translated attributes 144 # Clone translated attributes
138 page.translations.each do |translation| 145 page.translations.each do |translation|
139 self.translations.create!(translation.attributes) 146 self.translations.create!(translation.attributes.except("id", "page_id", "created_at", "updated_at"))
140 end 147 end
141 148
142 # Clone asset references 149 # Clone asset references
@@ -149,6 +156,16 @@ class Page < ActiveRecord::Base
149 published_at.nil? ? true : published_at < Time.now 156 published_at.nil? ? true : published_at < Time.now
150 end 157 end
151 158
159 def effective_lang
160 if translated_locales.empty?
161 return 'de'
162 elsif translated_locales.include?(I18n.locale)
163 return I18n.locale
164 else
165 return translated_locales.first
166 end
167 end
168
152 # Returns true if a page has translations where one of them is significantly 169 # Returns true if a page has translations where one of them is significantly
153 # older than the other. 170 # older than the other.
154 # Takes the I18n.default locale and a second :locale to test if the 171 # Takes the I18n.default locale and a second :locale to test if the
@@ -165,8 +182,8 @@ class Page < ActiveRecord::Base
165 182
166 translations = self.translations 183 translations = self.translations
167 184
168 default = *(translations.select {|x| x.locale == I18n.default_locale}) 185 default = translations.find {|x| x.locale.to_s == I18n.default_locale.to_s }
169 custom = *(translations.select {|x| x.locale == options[:locale]}) 186 custom = translations.find {|x| x.locale.to_s == options[:locale].to_s }
170 187
171 if translations.size > 1 && default && custom 188 if translations.size > 1 && default && custom
172 difference = (default.updated_at - custom.updated_at).to_i.abs 189 difference = (default.updated_at - custom.updated_at).to_i.abs
@@ -215,11 +232,6 @@ class Page < ActiveRecord::Base
215 links = links.reject { |l| l[:href] =~ /system\/uploads/ } 232 links = links.reject { |l| l[:href] =~ /system\/uploads/ }
216 locales = I18n.available_locales.reject {|l| l == :root} 233 locales = I18n.available_locales.reject {|l| l == :root}
217 234
218 if xml_doc.find("//p/aggregate")[0]
219 aggregate_tags = xml_doc.find("//aggregate")
220 aggregate_tags[0].parent.replace_with aggregate_tags[0]
221 end
222
223 links.each do |link| 235 links.each do |link|
224 unless locales.include? link[:href].slice(1,2).to_sym 236 unless locales.include? link[:href].slice(1,2).to_sym
225 unless link[:href] =~ /sytem\/uploads/ 237 unless link[:href] =~ /sytem\/uploads/
@@ -238,4 +250,4 @@ class Page < ActiveRecord::Base
238 end 250 end
239 end 251 end
240 252
241end \ No newline at end of file 253end
diff --git a/app/models/permission.rb b/app/models/permission.rb
index 438538e..1383a4b 100644
--- a/app/models/permission.rb
+++ b/app/models/permission.rb
@@ -1,4 +1,4 @@
1class Permission < ActiveRecord::Base 1class Permission < ApplicationRecord
2 # Validations 2 # Validations
3 validates_presence_of :user_id, :node_id, :granted 3 validates_presence_of :user_id, :node_id, :granted
4 validates_inclusion_of :granted, :in => [true, false] 4 validates_inclusion_of :granted, :in => [true, false]
@@ -8,6 +8,6 @@ class Permission < ActiveRecord::Base
8 belongs_to :node 8 belongs_to :node
9 9
10 # Named scopes 10 # Named scopes
11 named_scope :for_node, lambda { |node| { :conditions => ['node_id = ?', (node.is_a? Node ? node.id : node)] } } 11 scope :for_node, ->(node) { where('node_id = ?', (node.is_a?(Node) ? node.id : node)) }
12 named_scope :for_user, lambda { |user| { :conditions => ['user_id = ?', (user.is_a? User ? user.id : user)] } } 12 scope :for_user, ->(user) { where('user_id = ?', (user.is_a?(User) ? user.id : user)) }
13end 13end
diff --git a/app/models/related_asset.rb b/app/models/related_asset.rb
index af09420..8f16460 100644
--- a/app/models/related_asset.rb
+++ b/app/models/related_asset.rb
@@ -1,8 +1,8 @@
1class RelatedAsset < ActiveRecord::Base 1class RelatedAsset < ApplicationRecord
2 belongs_to :page 2 belongs_to :page
3 belongs_to :asset 3 belongs_to :asset
4 4
5 acts_as_list :scope => :page_id 5 acts_as_list :scope => :page_id
6 6
7 default_scope :order => "position ASC" 7 default_scope -> { order("position ASC") }
8end \ No newline at end of file 8end
diff --git a/app/models/user.rb b/app/models/user.rb
index ce5503f..92ac33a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,6 +1,6 @@
1require 'digest/sha1' 1require 'digest/sha1'
2 2
3class User < ActiveRecord::Base 3class User < ApplicationRecord
4 # Mixins and Plugins 4 # Mixins and Plugins
5 include Authentication 5 include Authentication
6 include Authentication::ByPassword 6 include Authentication::ByPassword
@@ -21,8 +21,6 @@ class User < ActiveRecord::Base
21 validates_format_of :email, :with => Authentication.email_regex, 21 validates_format_of :email, :with => Authentication.email_regex,
22 :message => Authentication.bad_email_message 22 :message => Authentication.bad_email_message
23 23
24 attr_accessible :login, :email, :password, :password_confirmation, :admin
25
26 # Authenticates a user by their login name and unencrypted password. Returns the user or nil. 24 # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
27 def self.authenticate(login, password) 25 def self.authenticate(login, password)
28 return nil if login.blank? || password.blank? 26 return nil if login.blank? || password.blank?
diff --git a/app/views/admin/_drafts.html.erb b/app/views/admin/_drafts.html.erb
index 58b946b..a35b0ab 100644
--- a/app/views/admin/_drafts.html.erb
+++ b/app/views/admin/_drafts.html.erb
@@ -17,9 +17,9 @@
17 <td class="actions"> 17 <td class="actions">
18 <%= link_to 'Show', node_path(draft.node) %> 18 <%= link_to 'Show', node_path(draft.node) %>
19 <%= link_to "Revisions", revision_path(draft.node.id) %> 19 <%= link_to "Revisions", revision_path(draft.node.id) %>
20 <%= link_to "Publish", publish_node_path(draft.node), :method => :put, :confirm => "Do you really want to publish?" %> 20 <%= button_to "Publish", publish_node_path(draft.node), method: :put, form: { data: { confirm: "Do you really want to publish?" } } %>
21 </td> 21 </td>
22 </tr> 22 </tr>
23 <% end %> 23 <% end %>
24 </table> 24 </table>
25</div> \ No newline at end of file 25</div>
diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb
index e8b39ce..6f217eb 100644
--- a/app/views/admin/_menu.html.erb
+++ b/app/views/admin/_menu.html.erb
@@ -1,7 +1,7 @@
1<%= language_selector %> 1<%= language_selector %>
2<%= link_to 'Logout', :controller => :sessions, :action => :destroy %> 2<%= button_to 'Logout', logout_path, method: :delete %>
3<%= link_to 'Overview', :controller => :admin, :action => 'index' %> 3<%= link_to 'Overview', admin_path %>
4<%= link_to 'Nodes', nodes_path, selected?('nodes') %> 4<%= link_to 'Nodes', nodes_path, selected?('nodes') %>
5<%= link_to 'Assets', assets_path, selected?('assets') %> 5<%= link_to 'Assets', assets_path, selected?('assets') %>
6<%= link_to 'User', users_path, selected?('users') %> 6<%= link_to 'User', users_path, selected?('users') %>
7<%= link_to 'Navigation', menu_items_path, selected?('menu_items') %> &gt;&nbsp; \ No newline at end of file 7<%= link_to 'Navigation', menu_items_path, selected?('menu_items') %> &gt;&nbsp;
diff --git a/app/views/admin/_recent_changes.html.erb b/app/views/admin/_recent_changes.html.erb
index 300d088..88b5e93 100644
--- a/app/views/admin/_recent_changes.html.erb
+++ b/app/views/admin/_recent_changes.html.erb
@@ -13,7 +13,7 @@
13 <td><%= truncated_title_for_node node %></td> 13 <td><%= truncated_title_for_node node %></td>
14 <td><%= node.unique_name %></td> 14 <td><%= node.unique_name %></td>
15 <td><%= node.draft.user.login rescue "" %></td> 15 <td><%= node.draft.user.login rescue "" %></td>
16 <td><%= node.updated_at.to_s(:db) %></td> 16 <td><%= node.updated_at.to_fs(:db) %></td>
17 <td class="actions"> 17 <td class="actions">
18 <%= link_to 'Show', node_path(node) %> 18 <%= link_to 'Show', node_path(node) %>
19 <%= link_to "Revisions", revision_path(:id => node.id) %> 19 <%= link_to "Revisions", revision_path(:id => node.id) %>
diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb
index 526aa88..2741db3 100644
--- a/app/views/admin/index.html.erb
+++ b/app/views/admin/index.html.erb
@@ -1,6 +1,15 @@
1<div id="admin_wizard">
2 <div class="admin_wizard_button"><%= link_to 'Create Update or Pressemitteilung', new_node_path, :only_path => false %></div>
3 <div class="admin_wizard_button"><a href="#" id="admin_wizard_my_work" class="button">Continue my work</a></div>
4 <div class="admin_wizard_button"><a href="#" id="admin_wizard_create_page" class="button">Add a page in the page tree</a></div>
5 <div class="admin_wizard_button"><%= link_to("Upload a new asset", new_asset_path, :only_path => false) %></div>
6</div>
7
1<p id="overview_toggle"> 8<p id="overview_toggle">
2 <a href="#" id="recent_changes_toggle" class="button">recent changes</a> 9 <a href="#" id="recent_changes_toggle" class="button">recent changes</a>
3 <a href="#" id="current_drafts_toggle" class="button">current drafts</a> 10 <a href="#" id="my_work_toggle" class="button">my work</a>
11 <a href="#" id="current_drafts_toggle" class="button">current drafts (<%= @drafts_count %>)</a>
12 <a href="#" id="admin_sitemap_toggle" class="button">site map</a>
4</p> 13</p>
5 14
6<div id="recent_changes_table"> 15<div id="recent_changes_table">
@@ -30,7 +39,41 @@
30 <%= node.lock_owner.login if node.lock_owner %> 39 <%= node.lock_owner.login if node.lock_owner %>
31 </td> 40 </td>
32 <td> 41 <td>
33 <%= node.draft ? node.draft.revision : node.head.revision %> 42 <%= link_to ( node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY" ) ), node_revisions_path(node) %>
43 </td>
44 </tr>
45 <% end %>
46 </table>
47</div>
48
49<div id="my_work_table">
50
51 <h1>My Work</h1>
52
53 <table class="node_table">
54 <tr class="header">
55 <th class="node_id">ID</th>
56 <th class="title">Title</th>
57 <th class="actions">Actions</th>
58 <th class="editor">Locked by</th>
59 <th class="revision">Rev.</th>
60 </tr>
61 <% @mynodes.each do |node| %>
62 <tr class="<%= cycle("even", "odd") %>">
63 <td class="node_id"><%= node.id %></td>
64 <td class="title">
65 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
66 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
67 </td>
68 <td class="actions">
69 <%= link_to 'show', node_path(node) %>
70 <%= link_to 'Revisions', node_revisions_path(node) %>
71 </td>
72 <td>
73 <%= node.lock_owner.login if node.lock_owner %>
74 </td>
75 <td>
76 <%= link_to ( node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY" ) ), node_revisions_path(node) %>
34 </td> 77 </td>
35 </tr> 78 </tr>
36 <% end %> 79 <% end %>
@@ -39,7 +82,7 @@
39 82
40<div id="current_drafts_table"> 83<div id="current_drafts_table">
41 84
42 <h1>Current Drafts</h1> 85 <h1>Current Drafts (<%= @drafts_count %>)</h1>
43 86
44 <table class="node_table"> 87 <table class="node_table">
45 <tr class="header"> 88 <tr class="header">
@@ -64,9 +107,41 @@
64 <%= node.lock_owner.login if node.lock_owner %> 107 <%= node.lock_owner.login if node.lock_owner %>
65 </td> 108 </td>
66 <td> 109 <td>
67 <%= node.draft ? node.draft.revision : node.head.revision %> 110 <%= link_to ( node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY" ) ), node_revisions_path(node) %>
111 </td>
112 </tr>
113 <% end %>
114 </table>
115</div>
116
117<div id="admin_sitemap_table">
118
119 <h1>Sitemap</h1>
120
121 <table class="node_table">
122 <tr class="header">
123 <th class="node_id">ID</th>
124 <th class="title">Title</th>
125 <th class="actions">Actions</th>
126 <th class="editor">Locked by</th>
127 </tr>
128 <% @sitemap.each do |node| %>
129 <% if !node.nil? %>
130 <tr class="<%= cycle("even", "odd") %>">
131 <td class="node_id" style="padding-left: <%= @sitemap_depth[node.id] * 30 %>px;"><%= node.id %></td>
132 <td class="title" style="padding-left: <%= @sitemap_depth[node.id] * 30 %>px;">
133 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
134 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
135 </td>
136 <td class="actions">
137 <%= link_to 'create subpage', new_node_path(:parent_id => node.id) %>
138 <%= link_to 'Revisions', node_revisions_path(node) %>
139 </td>
140 <td>
141 <%= node.lock_owner.login if node.lock_owner %>
68 </td> 142 </td>
69 </tr> 143 </tr>
70 <% end %> 144 <% end %>
145 <% end %>
71 </table> 146 </table>
72</div> \ No newline at end of file 147</div>
diff --git a/app/views/admin/search_results.html.erb b/app/views/admin/search_results.html.erb
new file mode 100644
index 0000000..671b665
--- /dev/null
+++ b/app/views/admin/search_results.html.erb
@@ -0,0 +1,7 @@
1<h1>Search Results</h1>
2
3<ul>
4<%- @results.each do |result| %>
5 <li><a href="<%= node_path(result) %>"><%= result.title %></a></li>
6<% end %>
7</ul>
diff --git a/app/views/assets/edit.html.erb b/app/views/assets/edit.html.erb
index d60db94..f198600 100644
--- a/app/views/assets/edit.html.erb
+++ b/app/views/assets/edit.html.erb
@@ -1,12 +1,24 @@
1<h1>Editing asset</h1> 1<h1>Editing asset</h1>
2 2
3<% form_for(@asset) do |f| %> 3<%= form_for(@asset, html: { multipart: true }) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5
6 <% if @asset.upload.present? %>
7 <p>
8 <strong>Current file:</strong>
9 <%= @asset.upload.url %>
10 (<%= number_to_human_size(@asset.upload.size) %>)
11 </p>
12 <% end %>
13
14 <p>
15 <label>Replace file:</label><br>
16 <%= f.file_field :upload %>
17 </p>
5 18
6 <p> 19 <p>
7 <%= f.submit 'Update' %> 20 <%= f.submit 'Update' %>
8 </p> 21 </p>
9<% end %> 22<% end %>
10 23
11<%= link_to 'Show', @asset %> | 24<%= link_to 'Show', @asset %> | <%= link_to 'Back', assets_path %>
12<%= link_to 'Back', assets_path %> \ No newline at end of file
diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb
index fc7c029..51fc486 100644
--- a/app/views/assets/index.html.erb
+++ b/app/views/assets/index.html.erb
@@ -10,12 +10,12 @@
10 </tr> 10 </tr>
11<% @assets.each do |asset| %> 11<% @assets.each do |asset| %>
12 <tr> 12 <tr>
13 <td><%= image_tag asset.upload.url(:thumb) %></td> 13 <td><%= image_tag asset.upload.url(:thumb), style: "max-width: 100px; max-height: 100px;" %></td>
14 <td><%= link_to asset.name, asset.upload.url %></td> 14 <td><%= link_to asset.name, asset.upload.url %></td>
15 <td><%= asset.upload.content_type %></td> 15 <td><%= asset.upload.content_type %></td>
16 <td><%= link_to 'Show', asset %></td> 16 <td><%= link_to 'Show', asset %></td>
17 <td><%= link_to 'Edit', edit_asset_path(asset) %></td> 17 <td><%= link_to 'Edit', edit_asset_path(asset) %></td>
18 <td><%= link_to 'Destroy', asset, :confirm => 'Are you sure?', :method => :delete %></td> 18 <td><%= button_to 'Destroy', asset, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
19 </tr> 19 </tr>
20<% end %> 20<% end %>
21</table> \ No newline at end of file 21</table>
diff --git a/app/views/assets/new.html.erb b/app/views/assets/new.html.erb
index 366488f..6c1310a 100644
--- a/app/views/assets/new.html.erb
+++ b/app/views/assets/new.html.erb
@@ -1,7 +1,7 @@
1<h1>New asset</h1> 1<h1>New asset</h1>
2 2
3<% form_for(@asset, :html => { :multipart => true }) do |f| %> 3<%= form_for(@asset, :html => { :multipart => true }) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5 5
6 <p> 6 <p>
7 <%= f.label :name %><br /> 7 <%= f.label :name %><br />
@@ -14,4 +14,4 @@
14 </p> 14 </p>
15<% end %> 15<% end %>
16 16
17<%= link_to 'Back', assets_path %> \ No newline at end of file 17<%= link_to 'Back', assets_path %>
diff --git a/app/views/assets/show.html.erb b/app/views/assets/show.html.erb
index a64987c..694be5a 100644
--- a/app/views/assets/show.html.erb
+++ b/app/views/assets/show.html.erb
@@ -6,7 +6,7 @@
6<table> 6<table>
7 <tr> 7 <tr>
8 <td>Thumbnail</td> 8 <td>Thumbnail</td>
9 <td><%= image_tag @asset.upload.url(:medium) %></td> 9 <td><%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %></td>
10 </tr> 10 </tr>
11 <tr> 11 <tr>
12 <td>Public Path</td> 12 <td>Public Path</td>
@@ -20,4 +20,4 @@
20 <td>Size</td> 20 <td>Size</td>
21 <td><%= "#{@asset.upload.size/1024} KB" %></td> 21 <td><%= "#{@asset.upload.size/1024} KB" %></td>
22 </tr> 22 </tr>
23</table> \ No newline at end of file 23</table>
diff --git a/app/views/content/_featured_articles.html.erb b/app/views/content/_featured_articles.html.erb
index 75e2e1d..6717c51 100644
--- a/app/views/content/_featured_articles.html.erb
+++ b/app/views/content/_featured_articles.html.erb
@@ -1,31 +1,56 @@
1<div id="featured_articles"> 1<div id="featured_articles">
2 <h2>Featured</h2> 2 <h2>Featured</h2>
3
4 <!-- %= link_to(
5 image_tag( '34c3-tuwat.1e4e25c.png' ),
6 "https://events.ccc.de/congress/2017/wiki/Main_Page",
7 :id => "34C3_icon",
8 :size => "155x90",
9 :title => "Chaos Communication Congress 2017"
10 )% -->
11
3 <%= link_to( 12 <%= link_to(
4 image_tag( 'chaosradio.png' ), 13 '<img src="/images/chaosradio.png" alt="Chaosradio">'.html_safe,
5 "http://chaosradio.ccc.de/", 14 "https://chaosradio.ccc.de/",
6 :id => "chaosradio_icon", 15 :id => "chaosradio_icon",
7 :title => "Chaosradio" 16 :title => "Chaosradio"
8 )%> 17 )%>
9 18
10 <%= link_to( 19 <%= link_to(
11 image_tag( 'ds.png' ), 20 '<img src="/images/media-ccc-de-banner.svg" width="155" height="45" alt="Media Dot CCC Dot de">'.html_safe,
12 "http://ds.ccc.de/", 21 "https://media.ccc.de",
22 :id => "media_ccc_de_icon",
23 :title => "Media Dot CCC Dot de"
24 )%>
25
26 <%= link_to(
27 '<img src="/images/ds.png" alt="Datenschleuder">'.html_safe,
28 "https://ds.ccc.de/",
13 :id => "ds_icon", 29 :id => "ds_icon",
14 :title => "Datenschleuder" 30 :title => "Datenschleuder"
15 )%> 31 )%>
16 32
17 <%= link_to( 33 <%= link_to(
18 image_tag( 'events.png' ), 34 '<img src="/images/events.png" alt="Events-Blog">'.html_safe,
19 "http://events.ccc.de/", 35 "https://events.ccc.de/",
20 :id => "events_icon", 36 :id => "events_icon",
21 :title => "Events Blog" 37 :title => "Events-Blog"
22 )%> 38 )%>
23 39
24 <%= link_to( 40 <%= link_to(
25 image_tag( 'twitter.png' ), 41 '<img src="/images/Fediverse.svg" width="64" height="64" alt="Fediverse">'.html_safe,
26 "https://twitter.com/chaosupdates", 42 "https://social.bau-ha.us/@ccc",
27 :id => "twitter_icon", 43 :rel => 'me',
28 :title => "Twitter" 44 :id => "fediverse_icon",
45 :title => "Fediverse"
29 )%> 46 )%>
47
48 <%= link_to(
49 '<img src="/images/Bluesky_Logo.svg" width="64" height="64" alt="bsky">'.html_safe,
50 "https://bsky.app/profile/ccc.de",
51 :id => "bluesky_icon",
52 :title => "bsky"
53 )%>
54
30</div> 55</div>
31 56
diff --git a/app/views/content/_main_navigation.html.erb b/app/views/content/_main_navigation.html.erb
index 67d4ecc..2fe8b77 100644
--- a/app/views/content/_main_navigation.html.erb
+++ b/app/views/content/_main_navigation.html.erb
@@ -4,4 +4,4 @@
4 <li><%= link_to_path item.title, item.path %></li> 4 <li><%= link_to_path item.title, item.path %></li>
5 <% end %> 5 <% end %>
6 </ul> 6 </ul>
7</div> \ No newline at end of file 7</div>
diff --git a/app/views/content/_search.html.erb b/app/views/content/_search.html.erb
index 9f61042..aa91424 100644
--- a/app/views/content/_search.html.erb
+++ b/app/views/content/_search.html.erb
@@ -1,8 +1,3 @@
1<% form_tag search_path, :method => 'get' do %> 1<%= form_tag search_path, :method => 'get' do %>
2<table> 2 <div><%= text_field_tag :search_term, params[:search_term], :placeholder => 'suchen', :type => 'search' %></div>
3 <tr> 3<% end %>
4 <td><%= text_field_tag :search_term, params[:search_term] %></td>
5 <td style="padding-top: 2px"><%= image_submit_tag("search_button.png") %></td>
6 </tr>
7</table>
8<% end %> \ No newline at end of file
diff --git a/app/views/content/_tags.html.erb b/app/views/content/_tags.html.erb
index d33bc10..f0e7210 100644
--- a/app/views/content/_tags.html.erb
+++ b/app/views/content/_tags.html.erb
@@ -1,8 +1,10 @@
1<% unless @page.nil? || @page.tags.empty? %>
1<div id="tags"> 2<div id="tags">
2 <h2>Tags</h2> 3 <h2>Tags</h2>
3 <ul class="teasertext"> 4 <ul class="teasertext">
4 <% @page.tags.each do |tag| %> 5 <% @page.tags.each do |tag| %>
5 <li><%= link_to tag.name, tag_path(:id => tag.name) %></li> 6 <li><%= link_to tag.name, tag_path(tag.name) %></li>
6 <% end %> 7 <% end %>
7 </ul> 8 </ul>
8</div> \ No newline at end of file 9</div>
10<% end %>
diff --git a/app/views/custom/page_templates/public/no_date_and_author.html.erb b/app/views/custom/page_templates/public/no_date_and_author.html.erb
index b019805..fa39e54 100644
--- a/app/views/custom/page_templates/public/no_date_and_author.html.erb
+++ b/app/views/custom/page_templates/public/no_date_and_author.html.erb
@@ -1,8 +1,8 @@
1<div class="article"> 1<div class="article" lang="<%= @page.effective_lang %>">
2 <h2 class="headline"><%= @page.title %></h2> 2 <h2 class="headline"><%= @page.title %></h2>
3 <p><%= sanitize( @page.abstract ) %></p> 3 <p><%= sanitize( @page.abstract ) %></p>
4 <div id="headline_image"><%= headline_image %></div> 4 <div id="headline_image"><%= headline_image %></div>
5 <%= aggregate?(@page.body) %> 5 <%= aggregate?(@page.body) %>
6</div> 6</div>
7 7
8<%= will_paginate(@content_collection) if @content_collection %> \ No newline at end of file 8<%= will_paginate(@content_collection) if @content_collection %>
diff --git a/app/views/custom/page_templates/public/no_date_and_author_with_map.html.erb b/app/views/custom/page_templates/public/no_date_and_author_with_map.html.erb
new file mode 100644
index 0000000..6e86edf
--- /dev/null
+++ b/app/views/custom/page_templates/public/no_date_and_author_with_map.html.erb
@@ -0,0 +1,8 @@
1<div class="article">
2 <h2 class="headline"><%= @page.title %></h2>
3 <p><%= sanitize( @page.abstract ) %></p>
4 <object data="/system/uploads/327/original/map.svg" type="image/svg+xml"/>
5 <%= aggregate?(@page.body) %>
6</div>
7
8<%= will_paginate(@content_collection) if @content_collection %>
diff --git a/app/views/custom/page_templates/public/no_title_abstract_date_and_author.html.erb b/app/views/custom/page_templates/public/no_title_abstract_date_and_author.html.erb
index 83cbff6..64e2a7c 100644
--- a/app/views/custom/page_templates/public/no_title_abstract_date_and_author.html.erb
+++ b/app/views/custom/page_templates/public/no_title_abstract_date_and_author.html.erb
@@ -1,6 +1,6 @@
1<div class="article"> 1<div class="article" lang="<%= @page.effective_lang %>">
2 <div id="headline_image"><%= headline_image %></div> 2 <div id="headline_image"><%= headline_image %></div>
3 <%= aggregate?(@page.body) %> 3 <%= aggregate?(@page.body) %>
4</div> 4</div>
5 5
6<%= will_paginate(@content_collection) if @content_collection %> \ No newline at end of file 6<%= will_paginate(@content_collection) if @content_collection %>
diff --git a/app/views/custom/page_templates/public/standard_template.html.erb b/app/views/custom/page_templates/public/standard_template.html.erb
index 8000af5..bbc8cd0 100644
--- a/app/views/custom/page_templates/public/standard_template.html.erb
+++ b/app/views/custom/page_templates/public/standard_template.html.erb
@@ -1,8 +1,8 @@
1<div class="article"> 1<div class="article" lang="<%= @page.effective_lang %>">
2 <h2 class="headline"><%= @page.title %></h2> 2 <h2 class="headline"><%= @page.title %></h2>
3 <div class="abstract"><p><%= sanitize( @page.abstract )%></p></div> 3 <div class="abstract"><p><%= sanitize( @page.abstract )%></p></div>
4 <div id="headline_image"><%= headline_image %></div> 4 <div id="headline_image"><%= headline_image %></div>
5 <div class="body"><%= aggregate?(@page.body) %></div> 5 <div class="body"><%= aggregate?(@page.body) %></div>
6</div> 6</div>
7 7
8<%= will_paginate(@content_collection) if @content_collection %> \ No newline at end of file 8<%= will_paginate(@content_collection) if @content_collection %>
diff --git a/app/views/custom/page_templates/public/title_only.html.erb b/app/views/custom/page_templates/public/title_only.html.erb
index 09c7455..42fe9a6 100644
--- a/app/views/custom/page_templates/public/title_only.html.erb
+++ b/app/views/custom/page_templates/public/title_only.html.erb
@@ -1,7 +1,7 @@
1<div class="article"> 1<div class="article" lang="<%= @page.effective_lang %>">
2 <h2 class="headline"><%= @page.title %></h2> 2 <h2 class="headline"><%= @page.title %></h2>
3 <div id="headline_image"><%= headline_image %></div> 3 <div id="headline_image"><%= headline_image %></div>
4 <%= aggregate?(@page.body) %> 4 <%= aggregate?(@page.body) %>
5</div> 5</div>
6 6
7<%= will_paginate(@content_collection) if @content_collection %> \ No newline at end of file 7<%= will_paginate(@content_collection) if @content_collection %>
diff --git a/app/views/custom/page_templates/public/update.html.erb b/app/views/custom/page_templates/public/update.html.erb
index 5ea277a..d5995ac 100644
--- a/app/views/custom/page_templates/public/update.html.erb
+++ b/app/views/custom/page_templates/public/update.html.erb
@@ -1,4 +1,4 @@
1<div class="article"> 1<div class="article" lang="<%= @page.effective_lang %>">
2 <h2 class="headline"><%= @page.title %></h2> 2 <h2 class="headline"><%= @page.title %></h2>
3 <div class="author_and_date"><%= date_for_page @page %>, <%= @page.user.try(:login) %></div> 3 <div class="author_and_date"><%= date_for_page @page %>, <%= @page.user.try(:login) %></div>
4 <div class="abstract"><p><%= sanitize( @page.abstract )%></p></div> 4 <div class="abstract"><p><%= sanitize( @page.abstract )%></p></div>
@@ -6,4 +6,4 @@
6 <div class="body"><%= aggregate?(@page.body) %></div> 6 <div class="body"><%= aggregate?(@page.body) %></div>
7</div> 7</div>
8 8
9<%= will_paginate(@content_collection) if @content_collection %> \ No newline at end of file 9<%= will_paginate(@content_collection) if @content_collection %>
diff --git a/app/views/custom/partials/_article.html.erb b/app/views/custom/partials/_article.html.erb
index 433c31c..b738ac7 100644
--- a/app/views/custom/partials/_article.html.erb
+++ b/app/views/custom/partials/_article.html.erb
@@ -1,7 +1,7 @@
1<div class="article_partial"> 1<div class="article_partial" lang="<%= page.effective_lang %>">
2 <h2 class="headline"><%= link_to_path page.title, page.node.unique_name %></h2> 2 <h2 class="headline"><%= link_to_path page.title, page.node.unique_name %></h2>
3 <div class="author_and_date"> 3 <div class="author_and_date">
4 <%= date_for_page page %>, <%= author_for_page page %> 4 <%= date_for_page page %>, <%= author_for_page page %>
5 </div> 5 </div>
6 <p class="excerpt"><%= page.abstract %> <%= link_to_path t(:more), page.node.unique_name %></p> 6 <p class="excerpt"><%= page.abstract %> <%= link_to_path t(:more), page.node.unique_name %></p>
7</div> \ No newline at end of file 7</div>
diff --git a/app/views/custom/partials/_no_date_and_author.html.erb b/app/views/custom/partials/_no_date_and_author.html.erb
index 61d6aac..fed02ac 100644
--- a/app/views/custom/partials/_no_date_and_author.html.erb
+++ b/app/views/custom/partials/_no_date_and_author.html.erb
@@ -1,4 +1,4 @@
1<div class="article_partial"> 1<div class="article_partial" lang="<%= page.effective_lang %>">
2 <h2 class="headline"><%= link_to page.title, content_path(page.node.unique_path) %></h2> 2 <h2 class="headline"><%= link_to page.title, content_path(page.node.unique_path) %></h2>
3 <p class="excerpt"><%= page.abstract %></p> 3 <p class="excerpt"><%= page.abstract %></p>
4</div> \ No newline at end of file 4</div>
diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb
index 17b6980..824cd66 100644
--- a/app/views/events/edit.html.erb
+++ b/app/views/events/edit.html.erb
@@ -6,8 +6,8 @@
6 6
7<h1>Editing event</h1> 7<h1>Editing event</h1>
8 8
9<% form_for(@event) do |f| %> 9<%= form_for(@event) do |f| %>
10 <%= f.error_messages %> 10 <%= form_error_messages(f) %>
11 11
12 <p> 12 <p>
13 <%= f.label :start_time %><br /> 13 <%= f.label :start_time %><br />
@@ -47,4 +47,4 @@
47 <p> 47 <p>
48 <%= f.submit 'Update' %> 48 <%= f.submit 'Update' %>
49 </p> 49 </p>
50<% end %> \ No newline at end of file 50<% end %>
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb
index c1b5b48..19b21ce 100644
--- a/app/views/events/index.html.erb
+++ b/app/views/events/index.html.erb
@@ -26,11 +26,11 @@
26 <td><%=h event.node_id %></td> 26 <td><%=h event.node_id %></td>
27 <td><%= link_to 'Show', event %></td> 27 <td><%= link_to 'Show', event %></td>
28 <td><%= link_to 'Edit', edit_event_path(event) %></td> 28 <td><%= link_to 'Edit', edit_event_path(event) %></td>
29 <td><%= link_to 'Destroy', event, :confirm => 'Are you sure?', :method => :delete %></td> 29 <td><%= button_to 'Destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
30 </tr> 30 </tr>
31<% end %> 31<% end %>
32</table> 32</table>
33 33
34<br /> 34<br />
35 35
36<%= link_to 'New event', new_event_path %> \ No newline at end of file 36<%= link_to 'New event', new_event_path %>
diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb
index 8c9812e..cd892c5 100644
--- a/app/views/events/new.html.erb
+++ b/app/views/events/new.html.erb
@@ -1,7 +1,7 @@
1<h1>New event</h1> 1<h1>New event</h1>
2 2
3<% form_for(@event) do |f| %> 3<%= form_for(@event) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5 5
6 <p> 6 <p>
7 <%= f.label :start_time %><br /> 7 <%= f.label :start_time %><br />
@@ -43,4 +43,4 @@
43 </p> 43 </p>
44<% end %> 44<% end %>
45 45
46<%= link_to 'Back', events_path %> \ No newline at end of file 46<%= link_to 'Back', events_path %>
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index 97b81df..890aeaa 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -4,16 +4,15 @@
4<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 4<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 <head> 5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7 <%= csrf_meta_tags %>
7 8
8 <title><%= "#{params[:controller]} | #{params[:action]}" %></title> 9 <title><%= "#{params[:controller]} | #{params[:action]}" %></title>
9 <%= javascript_include_tag 'jquery-1.3.2.min' %>
10 <%= javascript_include_tag 'jquery-ui-1.7.2.custom.min' %>
11 <%= javascript_include_tag 'jquery.hotkeys' %>
12 <%= javascript_include_tag 'tiny_mce/jquery.tinymce.js' %>
13 <%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %> 10 <%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
14 <%= stylesheet_link_tag 'admin' %> 11 <%= javascript_include_tag 'admin_bundle' %>
15 <%= javascript_include_tag 'admin_search.js' %> 12 <%= tinymce_assets %>
16 <%= javascript_include_tag 'admin_interface.js' %> 13 <link rel="stylesheet" href="/stylesheets/admin.css">
14 <script src="/javascripts/admin_search.js"></script>
15 <script src="/javascripts/admin_interface.js"></script>
17 </head> 16 </head>
18 17
19 <body> 18 <body>
@@ -34,7 +33,7 @@
34 <% end %> 33 <% end %>
35 </div> 34 </div>
36 <div id="content"> 35 <div id="content">
37 <%= yield :layout %> 36 <%= yield %>
38 </div> 37 </div>
39 38
40 <div id="results"></div> 39 <div id="results"></div>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 3c95d75..48e0a5b 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,47 +1,74 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 1<!DOCTYPE HTML>
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 2
4<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 3<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 <head> 4 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6 <meta name="viewport" content="width=device-width,initial-scale=1"/>
7 <meta name="description" content="Der Chaos Computer Club ist eine galaktische Gemeinschaft von Lebewesen für Informationsfreiheit und Technikfolgenabschätzung."/>
8
9 <meta property="og:image" content="https://www.ccc.de/images/chaosknoten.svg" />
10 <meta property="og:description" content="Der Chaos Computer Club ist eine galaktische Gemeinschaft von Lebewesen für Informationsfreiheit und Technikfolgenabschätzung." />
7 11
8 <title><%= page_title %></title> 12 <title><%= page_title %></title>
9 <%= stylesheet_link_tag "ccc" %> 13 <link rel="stylesheet" href="/stylesheets/ccc.css">
10 <%= javascript_include_tag 'jquery-1.3.2.min' %> 14 <script src="/javascripts/jquery-1.3.2.min.js"></script>
11 <%= javascript_include_tag 'shadowbox/shadowbox' %> 15 <script src="/javascripts/shadowbox/shadowbox.js"></script>
12 <%= stylesheet_link_tag "shadowbox" %> 16 <link rel="stylesheet" href="/stylesheets/shadowbox.css">
13 <%= javascript_include_tag 'public' %> 17 <script src="/javascripts/public.js"></script>
18
19 <%= auto_discovery_link_tag(:atom, '/rss/updates.xml', title: "ATOM") %>
20 <%= auto_discovery_link_tag(:rss, '/rss/updates.rdf', title: "RSS") %>
21
22 <script>
23 (function() { document.addEventListener("DOMContentLoaded", function() {
24 if (localStorage.getItem('override-prefers-color-scheme', false))
25 document.getElementById("light-mode").checked = true;
26 }); })();
27 </script>
14 28
15 <%= auto_discovery_link_tag(:atom, {:locale => :de, :controller => "rss", :action => "updates", :format => :xml}) %>
16 <%= auto_discovery_link_tag(:rss, {:locale => :de, :controller => "rss", :action => "updates", :format => :rdf}) %>
17 </head> 29 </head>
18 30
19 <body> 31 <body lang="<%= @page ? @page.effective_lang : 'de' %>">
20 <div id="wrapper"> 32 <div id="wrapper">
21 <div id="header"> 33 <div id="header">
22 <%= link_to_path(image_tag("header.png"), "/home") %> 34 <img src="/images/header.png" alt="">
23 </div> 35 </div>
24 <div id="search"> 36 <div id="toolbox">
25 <%= render :partial => "content/search" %> 37 <div id="search">
38 <%= render :partial => "content/search" %>
39 </div>
40 <div id="light-mode-div">
41 <input id="light-mode" type="checkbox" aria-label="Switch between dark and light mode" /><label for="light-mode"><span class="hide-me">lights</span></label>
42 </div>
43 <div id="burger-div">
44 <input type="checkbox" id="menu-toggle" class="menu-checkbox">
45 <label for="menu-toggle" class="burger-menu"><span></span><span></span><span></span></label>
46 </div>
26 </div> 47 </div>
27 <div id="left_column"> 48 <div id="left_column">
28 <%= main_menu %> 49 <%= main_menu %>
29 50
30 <%= language_selector %>
31 <% if current_user && @page.node %> 51 <% if current_user && @page.node %>
32 <%= link_to "Edit", node_path(:id => @page.node) %> 52 <div class="main_navigation">
53 <h2>Admin</h2>
54 <ul>
55 <li><%= link_to raw('<span class="inactive admin_edit_link">⚙️ Overview</span>'), admin_path %></li>
56 <li><%= link_to raw('<span class="inactive admin_edit_link">✎ Edit</span>'), node_path(@page.node) %></li>
57 </ul>
58 </div>
33 <% end %> 59 <% end %>
34 60
35 <%= calendar %> 61 <%= calendar %>
36 </div> 62 </div>
37 <div id="center_column"> 63 <div id="center_column">
38 <%= yield :layout %> 64 <%= yield :layout %>
39
40 <div id="footer"> 65 <div id="footer">
41 <br /> 66 <br />
42 <br />
43 <p style="text-align: center"> 67 <p style="text-align: center">
44 <%= link_to t(:sponsors), content_path("sponsors") %> 68 <%= link_to "Impressum", content_path("imprint") %>
69 <%= link_to "Datenschutz", content_path("datenschutz") %>
70 <%= language_selector %>
71 <!-- %= link_to t(:sponsors), content_path("sponsors") % -->
45 </p> 72 </p>
46 </div> 73 </div>
47 </div> 74 </div>
@@ -50,5 +77,6 @@
50 <%= featured_articles %> 77 <%= featured_articles %>
51 </div> 78 </div>
52 </div> 79 </div>
80
53 </body> 81 </body>
54</html> \ No newline at end of file 82</html>
diff --git a/app/views/layouts/pages.html.erb b/app/views/layouts/pages.html.erb
index 327e0eb..70ceece 100644
--- a/app/views/layouts/pages.html.erb
+++ b/app/views/layouts/pages.html.erb
@@ -4,6 +4,8 @@
4<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 4<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5<head> 5<head>
6 <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> 6 <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
7 <meta name="viewport" content="width=device-width,initial-scale=1" />
8 <meta property="og:image" content="https://www.ccc.de/images/chaosknoten.svg" />
7 <title>Pages: <%= controller.action_name %></title> 9 <title>Pages: <%= controller.action_name %></title>
8 <%= stylesheet_link_tag 'scaffold' %> 10 <%= stylesheet_link_tag 'scaffold' %>
9</head> 11</head>
diff --git a/app/views/menu_items/edit.html.erb b/app/views/menu_items/edit.html.erb
index 9ea0fcc..9891708 100644
--- a/app/views/menu_items/edit.html.erb
+++ b/app/views/menu_items/edit.html.erb
@@ -1,6 +1,6 @@
1<h1>Edit Menu Item</h1> 1<h1>Edit Menu Item</h1>
2 2
3<% form_for @menu_item do |f| %> 3<%= form_for @menu_item do |f| %>
4 <table> 4 <table>
5 5
6 <tr> 6 <tr>
@@ -29,4 +29,4 @@
29 <td class="right"><%= f.submit 'Update' %></td> 29 <td class="right"><%= f.submit 'Update' %></td>
30 </tr> 30 </tr>
31 </table> 31 </table>
32<% end %> \ No newline at end of file 32<% end %>
diff --git a/app/views/menu_items/index.html.erb b/app/views/menu_items/index.html.erb
index 123a07a..c52c150 100644
--- a/app/views/menu_items/index.html.erb
+++ b/app/views/menu_items/index.html.erb
@@ -14,13 +14,10 @@
14 <td class="menu_item_title"><%= menu_item.title %></td> 14 <td class="menu_item_title"><%= menu_item.title %></td>
15 <td><%= link_to "Edit", edit_menu_item_path(menu_item) %></td> 15 <td><%= link_to "Edit", edit_menu_item_path(menu_item) %></td>
16 <td> 16 <td>
17 <%= link_to( 17 <%= button_to "Delete", menu_item_path(menu_item),
18 "Delete", 18 method: :delete,
19 menu_item_path(menu_item), 19 form: { data: { confirm: "Are you sure?" } } %>
20 :method => :delete,
21 :confirm => "Are you sure?"
22 ) %>
23 </td> 20 </td>
24 </tr> 21 </tr>
25 <% end %> 22 <% end %>
26</table> \ No newline at end of file 23</table>
diff --git a/app/views/menu_items/new.html.erb b/app/views/menu_items/new.html.erb
index 64b9abb..68081d0 100644
--- a/app/views/menu_items/new.html.erb
+++ b/app/views/menu_items/new.html.erb
@@ -1,6 +1,6 @@
1<h1>Add Menu Item</h1> 1<h1>Add Menu Item</h1>
2 2
3<% form_for @menu_item do |f| %> 3<%= form_for @menu_item do |f| %>
4 <table> 4 <table>
5 5
6 <tr> 6 <tr>
@@ -29,4 +29,4 @@
29 <td class="right"><%= f.submit 'Create' %></td> 29 <td class="right"><%= f.submit 'Create' %></td>
30 </tr> 30 </tr>
31 </table> 31 </table>
32<% end %> \ No newline at end of file 32<% end %>
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb
index 8e27d0f..b45c700 100644
--- a/app/views/nodes/edit.html.erb
+++ b/app/views/nodes/edit.html.erb
@@ -2,109 +2,89 @@
2 <%= link_to 'metadata', '#', :id => 'button', :class => "unselected" %> 2 <%= link_to 'metadata', '#', :id => 'button', :class => "unselected" %>
3 <%= link_to 'Show', @node %> 3 <%= link_to 'Show', @node %>
4 <%= link_to 'Preview', preview_page_path(@draft) %> 4 <%= link_to 'Preview', preview_page_path(@draft) %>
5 <%= link_to 'Publish', publish_node_path, :method => :put, :confirm => "Publish this draft?" %> 5 <%= button_to 'Publish', publish_node_path(@node), method: :put, form: { data: { confirm: "Publish this draft?" } } %>
6 <%= link_to 'Revisions', node_revisions_path(@node) %> 6 <%= link_to 'Revisions', node_revisions_path(@node) %>
7<% end %> 7<% end %>
8 8
9<div id="page_editor"> 9<div id="page_editor">
10<% form_for(@node) do |f| %> 10<%= form_for(@node) do |f| %>
11 <%= f.error_messages %> 11 <% if @node.errors.any? %>
12 <div class="error_messages">
13 <ul><% @node.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul>
14 </div>
15 <% end %>
12 16
13 <div id="metadata"> 17 <div id="metadata">
14 <table> 18 <div class="node_description">Event</div>
15 <tr> 19 <div class="node_content"><%= event_information %></div>
16 <td class="description">Event</td> 20
17 <td><%= event_information %></td> 21 <div class="node_description">Slug</div>
18 </tr> 22 <div class="node_content">
19 <tr> 23 <%= f.text_field(
20 <td class="description">Slug</td> 24 :staged_slug, :value => @node.staged_slug || @node.slug
21 <td> 25 )
22 <%= 26 %>
23 f.text_field( 27 </div>
24 :staged_slug, :value => @node.staged_slug || @node.slug 28
25 ) 29 <div class="node_description">parent</div>
26 %> 30 <div class="node_content">
27 </td> 31 <%= text_field_tag :move_to_search_term, @node.parent.title rescue "" %>
28 </tr> 32 <div id="search_results">
29 <tr>
30 <td class="description">parent</td>
31 <td>
32 <%= text_field_tag :move_to_search_term, @node.parent.title rescue "" %>
33 <div id="search_results">
34 33
35 </div> 34 </div>
36 <%= f.hidden_field( 35 <%= f.hidden_field(
37 :staged_parent_id, 36 :staged_parent_id,
38 :value => @node.staged_parent_id || @node.parent_id 37 :value => @node.staged_parent_id || @node.parent_id
39 ) 38 )
40 %> 39 %>
41 </td> 40 </div>
42 </tr>
43 41
44 <% fields_for @draft do |d| %> 42 <%= fields_for @draft do |d| %>
45 <tr> 43 <div class="node_description">Tags - comma seperated</div>
46 <td class="description">Tags - comma seperated</td> 44 <div class="node_content"><%= text_field_tag :tag_list, @draft.tag_list %></div>
47 <td><%= text_field_tag :tag_list, @draft.tag_list %></td> 45
48 </tr> 46 <div class="node_description">Publish at</div>
49 <tr> 47 <div class="node_content"><%= d.datetime_select :published_at, :value => @draft.published_at %></div>
50 <td class="description">Publish at</td> 48
51 <td><%= d.datetime_select :published_at, :value => @draft.published_at %></td> 49 <div class="node_description">Template</div>
52 </tr> 50 <div class="node_content"><%= d.select :template_name, custom_page_templates, {:prompt => 'Select Template'} %></div>
53 <tr> 51
54 <td class="description">Template</td> 52 <div class="node_description">Author</div>
55 <td><%= d.select :template_name, custom_page_templates, {:prompt => 'Select Template'} %></td> 53 <div class="node_content"><%= d.select :user_id, user_list %></div>
56 </tr> 54
57 <tr> 55 <div class="node_description">Images</div>
58 <td class="description">Author</td> 56 <div class="node_content">
59 <td><%= d.select :user_id, user_list %></td> 57 <ul id="image_box" rel="<%= @draft.id %>">
60 </tr> 58 <% @draft.assets.images.each do |image| %>
61 <tr> 59 <li rel="images_<%= image.id %>">
62 <td class="description">Images</td> 60 <%= image_tag(image.upload.url(:thumb)) %>
63 <td> 61 </li>
64 <ul id="image_box" rel="<%= @draft.id %>"> 62 <% end %>
65 <% @draft.assets.images.each do |image| %> 63 </ul>
66 <li rel="images_<%= image.id %>"> 64 <div class="clear_left right">
67 <%= image_tag(image.upload.url(:thumb)) %> 65 <a id="image_browser_toggle" class="unselected" href="#">image browser</a>
68 </li> 66 </div>
69 <% end %> 67 <div id="image_browser">
70 </ul> 68 <ul>
71 <div class="clear_left right"> 69 <% Asset.images.each do |image| %>
72 <a id="image_browser_toggle" class="unselected" href="#">image browser</a> 70 <li rel="images_<%= image.id %>"><%= image_tag(image.upload.url(:thumb)) %></li>
73 </div> 71 <% end %>
74 <div id="image_browser"> 72 </ul>
75 <ul> 73 </div>
76 <% Asset.images.each do |image| %> 74 </div>
77 <li rel="images_<%= image.id %>"><%= image_tag(image.upload.url(:thumb)) %></li>
78 <% end %>
79 </ul>
80 </div>
81 </td>
82 </tr>
83 </table>
84 </div> 75 </div>
85 76
86 <table id="content"> 77 <div id="content">
87 <tr> 78 <div class="node_description">Title</div>
88 <th class="description"></th> 79 <div class="node_content"><%= d.text_field :title %></div>
89 <th class="content"></th> 80
90 </tr> 81 <div class="node_description">Abstract</div>
91 <tr> 82 <div class="node_content"><%= d.text_area :abstract %></div>
92 <td class="description">Title</td> 83
93 <td><%= d.text_field :title %></td> 84 <div class="node_description">Body</div>
94 </tr> 85 <div class="node_content"><%= d.text_area :body, :class => 'with_editor' %></div>
95 <tr> 86
96 <td class="description">Abstract</td> 87 <div><%= d.submit 'save' %></div>
97 <td><%= d.text_area :abstract %></td>
98 </tr>
99 <tr>
100 <td class="description">Body</td>
101 <td><%= d.text_area :body, :class => 'with_editor' %></td>
102 </tr>
103 <tr>
104 <td></td>
105 <td class="right"><%= d.submit 'save' %></td>
106 </tr>
107 </table>
108 <% end %> 88 <% end %>
109<% end %> 89<% end %>
110</div> \ No newline at end of file 90</div>
diff --git a/app/views/nodes/index.html.erb b/app/views/nodes/index.html.erb
index bf01645..e5a55d4 100644
--- a/app/views/nodes/index.html.erb
+++ b/app/views/nodes/index.html.erb
@@ -27,7 +27,7 @@
27 <%= node.lock_owner.login if node.lock_owner %> 27 <%= node.lock_owner.login if node.lock_owner %>
28 </td> 28 </td>
29 <td> 29 <td>
30 <%= node.draft ? node.draft.revision : node.head.revision %> 30 <%= node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY") %>
31 </td> 31 </td>
32 </tr> 32 </tr>
33 <% end %> 33 <% end %>
diff --git a/app/views/nodes/new.html.erb b/app/views/nodes/new.html.erb
index 850207b..028d727 100644
--- a/app/views/nodes/new.html.erb
+++ b/app/views/nodes/new.html.erb
@@ -1,11 +1,14 @@
1<h1>Create new node</h1> 1<h1>Create new node</h1>
2 2
3<%= error_messages_for( :node ).gsub("Slug", "Title") %> 3<% if @node.errors.any? %>
4 4 <div class="error_messages">
5 <ul><% @node.errors.full_messages.each do |msg| %><li><%= msg.to_s.gsub("Slug", "Title") %></li><% end %></ul>
6 </div>
7<% end %>
5 8
6<p>What kind of node do you want to create?</p> 9<p>What kind of node do you want to create?</p>
7 10
8<% form_tag nodes_path do %> 11<%= form_tag nodes_path do %>
9<table id="new_node"> 12<table id="new_node">
10 <tr> 13 <tr>
11 <td class="description">Type</td> 14 <td class="description">Type</td>
@@ -20,7 +23,11 @@
20 </p> 23 </p>
21 <p> 24 <p>
22 <%= radio_button_tag :kind, "update" %> 25 <%= radio_button_tag :kind, "update" %>
23 Update / Press release ( is automatically created in /updates ) 26 Update ( is automatically created in /updates/<%= Time.now.year.to_s %>/ and gets tag "update" )
27 </p>
28 <p>
29 <%= radio_button_tag :kind, "press_release" %>
30 Pressemitteilung ( is automatically created in /updates/<%= Time.now.year.to_s %>/ and gets tags "update, pressemitteilung" )
24 </p> 31 </p>
25 </td> 32 </td>
26 </tr> 33 </tr>
@@ -31,8 +38,8 @@
31 <tr id="parent_search_field"> 38 <tr id="parent_search_field">
32 <td class="description">Parent</td> 39 <td class="description">Parent</td>
33 <td> 40 <td>
34 <%= text_field_tag :parent_search_term %> 41 <%= text_field_tag :parent_search_term, @parent_name %>
35 <%= hidden_field_tag :parent_id %> 42 <%= hidden_field_tag :parent_id, @parent_id %>
36 <div id="search_results"> 43 <div id="search_results">
37 44
38 </div> 45 </div>
@@ -43,4 +50,4 @@
43 <td class="right"><%= submit_tag "Create" %></td> 50 <td class="right"><%= submit_tag "Create" %></td>
44 </tr> 51 </tr>
45</table> 52</table>
46<% end %> \ No newline at end of file 53<% end %>
diff --git a/app/views/nodes/update.js.erb b/app/views/nodes/update.js.erb
index be26fab..35dfeee 100644
--- a/app/views/nodes/update.js.erb
+++ b/app/views/nodes/update.js.erb
@@ -1,3 +1,5 @@
1$("#flash").html( 1<% if flash[:notice] %>
2 "<span><%= escape_javascript(flash.delete(:notice)) %></span>" 2 $("#flash").html(
3); \ No newline at end of file 3 "<span><%= escape_javascript(flash.delete(:notice)) %></span>"
4 );
5<% end %>
diff --git a/app/views/occurrences/edit.html.erb b/app/views/occurrences/edit.html.erb
index 6a81188..aa4f6e0 100644
--- a/app/views/occurrences/edit.html.erb
+++ b/app/views/occurrences/edit.html.erb
@@ -1,7 +1,7 @@
1<h1>Editing occurrence</h1> 1<h1>Editing occurrence</h1>
2 2
3<% form_for(@occurrence) do |f| %> 3<%= form_for(@occurrence) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5 5
6 <p> 6 <p>
7 <%= f.label :summary %><br /> 7 <%= f.label :summary %><br />
@@ -29,4 +29,4 @@
29<% end %> 29<% end %>
30 30
31<%= link_to 'Show', @occurrence %> | 31<%= link_to 'Show', @occurrence %> |
32<%= link_to 'Back', occurrences_path %> \ No newline at end of file 32<%= link_to 'Back', occurrences_path %>
diff --git a/app/views/occurrences/index.html.erb b/app/views/occurrences/index.html.erb
index 06dbf07..0e99857 100644
--- a/app/views/occurrences/index.html.erb
+++ b/app/views/occurrences/index.html.erb
@@ -18,11 +18,11 @@
18 <td><%=h occurrence.event_id %></td> 18 <td><%=h occurrence.event_id %></td>
19 <td><%= link_to 'Show', occurrence %></td> 19 <td><%= link_to 'Show', occurrence %></td>
20 <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td> 20 <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td>
21 <td><%= link_to 'Destroy', occurrence, :confirm => 'Are you sure?', :method => :delete %></td> 21 <td><%= button_to 'Destroy', occurrence, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
22 </tr> 22 </tr>
23<% end %> 23<% end %>
24</table> 24</table>
25 25
26<br /> 26<br />
27 27
28<%= link_to 'New occurrence', new_occurrence_path %> \ No newline at end of file 28<%= link_to 'New occurrence', new_occurrence_path %>
diff --git a/app/views/occurrences/new.html.erb b/app/views/occurrences/new.html.erb
index 0a77af1..c05ce40 100644
--- a/app/views/occurrences/new.html.erb
+++ b/app/views/occurrences/new.html.erb
@@ -1,7 +1,7 @@
1<h1>New occurrence</h1> 1<h1>New occurrence</h1>
2 2
3<% form_for(@occurrence) do |f| %> 3<%= form_for(@occurrence) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5 5
6 <p> 6 <p>
7 <%= f.label :summary %><br /> 7 <%= f.label :summary %><br />
@@ -28,4 +28,4 @@
28 </p> 28 </p>
29<% end %> 29<% end %>
30 30
31<%= link_to 'Back', occurrences_path %> \ No newline at end of file 31<%= link_to 'Back', occurrences_path %>
diff --git a/app/views/pages/edit.html.erb b/app/views/pages/edit.html.erb
index 749d7e3..8b1242c 100644
--- a/app/views/pages/edit.html.erb
+++ b/app/views/pages/edit.html.erb
@@ -1,7 +1,7 @@
1<h1>Editing page</h1> 1<h1>Editing page</h1>
2 2
3<% form_for(@page) do |f| %> 3<%= form_for(@page) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5 5
6 <p> 6 <p>
7 <%= f.label :title %><br /> 7 <%= f.label :title %><br />
diff --git a/app/views/pages/index.html.erb b/app/views/pages/index.html.erb
index 16539da..91e5359 100644
--- a/app/views/pages/index.html.erb
+++ b/app/views/pages/index.html.erb
@@ -10,9 +10,9 @@
10 <tr> 10 <tr>
11 <td><%=h page.node_id %></td> 11 <td><%=h page.node_id %></td>
12 <td><%=h page.title %></td> 12 <td><%=h page.title %></td>
13 <td><%= link_to 'Show', link_to_path(page.node.unique_path) %></td> 13 <td><%= link_to 'Show', content_path(:page_path => page.node.unique_path) %></td>
14 <td><%= link_to 'Edit', edit_page_path(page) %></td> 14 <td><%= link_to 'Edit', edit_page_path(page) %></td>
15 <td><%= link_to 'Destroy', page, :confirm => 'Are you sure?', :method => :delete %></td> 15 <td><%= button_to 'Destroy', page, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
16 </tr> 16 </tr>
17<% end %> 17<% end %>
18</table> 18</table>
diff --git a/app/views/pages/new.html.erb b/app/views/pages/new.html.erb
index b27dc62..2758faf 100644
--- a/app/views/pages/new.html.erb
+++ b/app/views/pages/new.html.erb
@@ -1,7 +1,7 @@
1<h1>New page</h1> 1<h1>New page</h1>
2 2
3<% form_for(@page) do |f| %> 3<%= form_for(@page) do |f| %>
4 <%= f.error_messages %> 4 <%= form_error_messages(f) %>
5 5
6 <p> 6 <p>
7 <%= f.label :node_id %><br /> 7 <%= f.label :node_id %><br />
diff --git a/app/views/revisions/diff.html.erb b/app/views/revisions/diff.html.erb
index f7ad79c..b8d061d 100644
--- a/app/views/revisions/diff.html.erb
+++ b/app/views/revisions/diff.html.erb
@@ -5,7 +5,7 @@
5 5
6<h1>Revisions#diff</h1> 6<h1>Revisions#diff</h1>
7 7
8<% form_tag diff_node_revisions_path do %> 8<%= form_tag diff_node_revisions_path do %>
9 <%= select_tag :start_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:start_revision].to_i) %> 9 <%= select_tag :start_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:start_revision].to_i) %>
10 <%= select_tag :end_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:end_revision].to_i) %> 10 <%= select_tag :end_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:end_revision].to_i) %>
11 <%= submit_tag 'Diff' %> 11 <%= submit_tag 'Diff' %>
@@ -38,7 +38,7 @@
38 </div> 38 </div>
39</pre> 39</pre>
40 40
41<%= javascript_include_tag 'cacycle_diff' %> 41<script src="/javascripts/cacycle_diff.js"></script>
42<script type="text/javascript" charset="utf-8"> 42<script type="text/javascript" charset="utf-8">
43 window.onload = function() { 43 window.onload = function() {
44 title1 = document.getElementById('start_title').innerHTML; 44 title1 = document.getElementById('start_title').innerHTML;
@@ -62,4 +62,4 @@
62 62
63 <h3>Body</h3> 63 <h3>Body</h3>
64 <p id="diffview_body"></p> 64 <p id="diffview_body"></p>
65</div> \ No newline at end of file 65</div>
diff --git a/app/views/revisions/index.html.erb b/app/views/revisions/index.html.erb
index dc9ad51..b875a4f 100644
--- a/app/views/revisions/index.html.erb
+++ b/app/views/revisions/index.html.erb
@@ -4,7 +4,6 @@
4 4
5<h2>Revisions for Node: <%= @node.unique_name %></h2> 5<h2>Revisions for Node: <%= @node.unique_name %></h2>
6 6
7<% form_tag diff_node_revisions_path(@node) do %>
8<table id="revisions"> 7<table id="revisions">
9 <tr class="header"> 8 <tr class="header">
10 <th>First</th> 9 <th>First</th>
@@ -14,8 +13,9 @@
14 <th>Editor</th> 13 <th>Editor</th>
15 <th>Date</th> 14 <th>Date</th>
16 <th></th> 15 <th></th>
16 <th></th>
17 </tr> 17 </tr>
18<% @node.pages.reverse.each do |page| %> 18<% (@pages || @node.pages.all).reverse.each do |page| %>
19 <tr> 19 <tr>
20 <td><%= radio_button_tag :start_revision, page.revision %></td> 20 <td><%= radio_button_tag :start_revision, page.revision %></td>
21 <td><%= radio_button_tag :end_revision, page.revision %></td> 21 <td><%= radio_button_tag :end_revision, page.revision %></td>
@@ -23,22 +23,36 @@
23 <td class="title"><%= page.title %></td> 23 <td class="title"><%= page.title %></td>
24 <td class="user"><%= page.editor.try(:login) %></td> 24 <td class="user"><%= page.editor.try(:login) %></td>
25 <td class="date"><%= page.updated_at %></td> 25 <td class="date"><%= page.updated_at %></td>
26 <td><%= link_to 'show', node_revision_path(@node, page) %></td>
26 <td> 27 <td>
27 <%= link_to 'show', node_revision_path(@node, page) %> 28 <%= button_to 'restore', restore_node_revision_path(@node, page),
28 </td> 29 method: :put,
29 <td> 30 form: { data: { confirm: "Restore this revision?" } } %>
30 <%= link_to(
31 'restore',
32 restore_node_revision_path(@node, page),
33 :method => :put,
34 :confirm => "Restore this revision?"
35 ) %>
36 </td> 31 </td>
37 </tr> 32 </tr>
38<% end %> 33<% end %>
39 <tr class="no_hover"> 34 <tr class="no_hover">
40 <td colspan="8" class="right"><%= submit_tag 'Diff revisions' %></td> 35 <td colspan="8" class="right">
36 <%= button_to 'Diff revisions', diff_node_revisions_path(@node),
37 method: :post,
38 form: { id: 'diff_form' } %>
39 </td>
41 </tr> 40 </tr>
42</table> 41</table>
43 42
44<% end %> \ No newline at end of file 43<script>
44 document.getElementById('diff_form').addEventListener('submit', function(e) {
45 var start = document.querySelector('input[name="start_revision"]:checked');
46 var end = document.querySelector('input[name="end_revision"]:checked');
47 if (start) {
48 var s = document.createElement('input');
49 s.type = 'hidden'; s.name = 'start_revision'; s.value = start.value;
50 this.appendChild(s);
51 }
52 if (end) {
53 var en = document.createElement('input');
54 en.type = 'hidden'; en.name = 'end_revision'; en.value = end.value;
55 this.appendChild(en);
56 }
57 });
58</script>
diff --git a/app/views/rss/recent_changes.xml.builder b/app/views/rss/recent_changes.xml.builder
index c3b3ec9..cce3b5d 100644
--- a/app/views/rss/recent_changes.xml.builder
+++ b/app/views/rss/recent_changes.xml.builder
@@ -2,19 +2,19 @@ xml.instruct!
2 2
3xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do 3xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do
4 xml.title("CCC.de Recent Change") 4 xml.title("CCC.de Recent Change")
5 xml.link(:href => "http://www.ccc.de/") 5 xml.link(:href => "https://www.ccc.de/")
6 xml.link(:rel => "self", :href => "/rss/updates.xml") 6 xml.link(:rel => "self", :href => "/rss/updates.xml")
7 xml.updated(@items.first.updated_at.xmlschema) 7 xml.updated(@items.first.updated_at.xmlschema)
8 xml.author do 8 xml.author do
9 xml.name("Chaos Computer Club e.V.") 9 xml.name("Chaos Computer Club e.V.")
10 end 10 end
11 xml.id("http://www.ccc.de/") 11 xml.id("https://www.ccc.de/")
12 12
13 @items.each do |item| 13 @items.each do |item|
14 xml.entry do 14 xml.entry do
15 xml.title(item.title) 15 xml.title(item.title)
16 xml.link( 16 xml.link(
17 :href => "http://www.ccc.de/#{item.node.unique_path}", 17 :href => "https://www.ccc.de/#{item.node.unique_path}",
18 :rel => "alternate" 18 :rel => "alternate"
19 ) 19 )
20 xml.id(content_url_helper(item.node.unique_path)) 20 xml.id(content_url_helper(item.node.unique_path))
@@ -26,4 +26,4 @@ xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do
26 26
27 end 27 end
28 28
29end \ No newline at end of file 29end
diff --git a/app/views/rss/updates.rdf.builder b/app/views/rss/updates.rdf.builder
index 00b6242..b02d34f 100644
--- a/app/views/rss/updates.rdf.builder
+++ b/app/views/rss/updates.rdf.builder
@@ -2,26 +2,26 @@ xml.instruct!
2xml.tag!("rdf:RDF", "xmlns:rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "xmlns:dc" => "http://purl.org/dc/elements/1.1/", "xmlns" => "http://purl.org/rss/1.0/") do 2xml.tag!("rdf:RDF", "xmlns:rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "xmlns:dc" => "http://purl.org/dc/elements/1.1/", "xmlns" => "http://purl.org/rss/1.0/") do
3 xml.tag!( "rdf:Description", "rdf:about" => "http://www.w3.org/TR/rdf-syntax-grammar", "dc:title"=>"RDF/XML Syntax Specification (Revised)") 3 xml.tag!( "rdf:Description", "rdf:about" => "http://www.w3.org/TR/rdf-syntax-grammar", "dc:title"=>"RDF/XML Syntax Specification (Revised)")
4 4
5 xml.channel do 5 xml.channel( "rdf:about" => "https://www.ccc.de/de/rss/updates.xml" ) do
6 xml.title("Chaos Computer Club: Updates") 6 xml.title("Chaos Computer Club: Updates")
7 xml.link("http://www.ccc.de") 7 xml.link("https://www.ccc.de")
8 xml.description("Kabelsalat ist gesund.") 8 xml.description("Kabelsalat ist gesund.")
9 xml.tag!("dc:date", @items.first.published_at.xmlschema) 9 xml.tag!("dc:date", @items.first.published_at.xmlschema)
10 end 10 end
11 11
12 xml.image( "rdf:about" => "http://www.ccc.de/images/chaosknoten.gif") do 12 xml.image( "rdf:about" => "https://www.ccc.de/images/chaosknoten.gif") do
13 xml.title("Chaos Computer Club (Chaosknoten)") 13 xml.title("Chaos Computer Club (Chaosknoten)")
14 xml.link("http://www.ccc.de") 14 xml.link("https://www.ccc.de")
15 xml.url("http://www.ccc.de/images/chaosknoten.gif") 15 xml.url("https://www.ccc.de/images/chaosknoten.gif")
16 end 16 end
17 17
18 @items.each do |item| 18 @items.each do |item|
19 xml.item("rdf:about" => content_url(:page_path => item.node.unique_path)) do 19 xml.item("rdf:about" => content_url(:page_path => item.node.unique_path)) do
20 xml.title(item.title) 20 xml.title(CGI.escapeHTML(item.title.to_s))
21 xml.link(content_url(:page_path => item.node.unique_path)) 21 xml.link(content_url(:page_path => item.node.unique_path))
22 xml.description(item.abstract) 22 xml.description(CGI.escapeHTML(item.abstract.to_s))
23 xml.tag!("dc:creator", item.user.login) 23 xml.tag!("dc:creator", (item.user ? item.user.login : "CCC"))
24 xml.tag!("dc:date", item.published_at.xmlschema) 24 xml.tag!("dc:date", item.published_at.xmlschema)
25 end 25 end
26 end 26 end
27end \ No newline at end of file 27end
diff --git a/app/views/rss/updates.xml.builder b/app/views/rss/updates.xml.builder
index c09c9c9..4b2e2f7 100644
--- a/app/views/rss/updates.xml.builder
+++ b/app/views/rss/updates.xml.builder
@@ -2,17 +2,17 @@ xml.instruct!
2 2
3xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do 3xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do
4 xml.title("Chaos Computer Club Updates") 4 xml.title("Chaos Computer Club Updates")
5 xml.link(:href => "http://www.ccc.de/") 5 xml.link(:href => "https://www.ccc.de/")
6 xml.link(:rel => "self", :href => "#{@host}/rss/updates") 6 xml.link(:rel => "self", :href => "#{@host}/rss/updates.xml")
7 xml.updated(@items.first.published_at.xmlschema) 7 xml.updated(@items.first.published_at.xmlschema)
8 xml.author do 8 xml.author do
9 xml.name("Chaos Computer Club e.V.") 9 xml.name("Chaos Computer Club e.V.")
10 end 10 end
11 xml.id("#{@host}/rss/updates") 11 xml.id("https://www.ccc.de/rss/updates")
12 12
13 @items.each do |item| 13 @items.each do |item|
14 xml.entry do 14 xml.entry do
15 xml.title(item.title) 15 xml.title(CGI.escapeHTML(item.title.to_s))
16 xml.link( 16 xml.link(
17 :href => content_url(:page_path => item.node.unique_path), 17 :href => content_url(:page_path => item.node.unique_path),
18 :rel => "alternate", 18 :rel => "alternate",
@@ -21,6 +21,7 @@ xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do
21 xml.id(content_url(:page_path => item.node.feed_id)) 21 xml.id(content_url(:page_path => item.node.feed_id))
22 xml.updated(item.updated_at.xmlschema) 22 xml.updated(item.updated_at.xmlschema)
23 xml.published(item.published_at.xmlschema) 23 xml.published(item.published_at.xmlschema)
24 xml.summary(CGI.escapeHTML(item.abstract.to_s))
24 xml.content(:type => "xhtml") do 25 xml.content(:type => "xhtml") do
25 xml.div(item.body, :xmlns => "http://www.w3.org/1999/xhtml") 26 xml.div(item.body, :xmlns => "http://www.w3.org/1999/xhtml")
26 end 27 end
@@ -28,4 +29,4 @@ xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do
28 29
29 end 30 end
30 31
31end \ No newline at end of file 32end
diff --git a/app/views/search/_search_result.html.erb b/app/views/search/_search_result.html.erb
index 14898a2..6cd01f8 100644
--- a/app/views/search/_search_result.html.erb
+++ b/app/views/search/_search_result.html.erb
@@ -1,6 +1,6 @@
1<% if node.head %> 1<% if node and node.head %>
2<div class="article_partial"> 2<div class="article_partial" lang="<%= node.head.effective_lang %>">
3 <h2 class="headline"><%= link_to node.head.title, content_path(node.unique_path) %></h2> 3 <h2 class="headline"><%= link_to node.head.title, content_path(node.unique_path) %></h2>
4 <p class="excerpt"><%= node.head.abstract %></p> 4 <p class="excerpt"><%= node.head.abstract %></p>
5</div> 5</div>
6<% end %> \ No newline at end of file 6<% end %>
diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb
index fef0912..3c10303 100644
--- a/app/views/sessions/new.html.erb
+++ b/app/views/sessions/new.html.erb
@@ -1,5 +1,5 @@
1<div id="login_form"> 1<div id="login_form">
2 <% form_tag session_path do -%> 2 <%= form_tag session_path do -%>
3 <table> 3 <table>
4 <tr> 4 <tr>
5 <td></td> 5 <td></td>
@@ -21,4 +21,4 @@
21 </tr> 21 </tr>
22 </table> 22 </table>
23 <% end -%> 23 <% end -%>
24</div> \ No newline at end of file 24</div>
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb
index 8117bcd..ddb7afd 100644
--- a/app/views/users/_user.html.erb
+++ b/app/views/users/_user.html.erb
@@ -7,13 +7,10 @@
7 <%= link_to "edit", edit_user_path(user) %> 7 <%= link_to "edit", edit_user_path(user) %>
8 </td> 8 </td>
9 <td> 9 <td>
10 <%= link_to( 10 <%= button_to "destroy", user_path(user),
11 "destroy", 11 method: :delete,
12 user_path(user), 12 form: { data: { confirm: "Do you really want to delete user #{user.login}?" } } %>
13 :method => :delete,
14 :confirm => "Do you really want to delete user #{user.login}?"
15 ) %>
16 </td> 13 </td>
17 <% end %> 14 <% end %>
18</tr> 15</tr>
19<% end %> \ No newline at end of file 16<% end %>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
index 226e821..df1005b 100644
--- a/app/views/users/edit.html.erb
+++ b/app/views/users/edit.html.erb
@@ -1,8 +1,13 @@
1<h1>Edit existing user</h1> 1<h1>Edit existing user</h1>
2 2
3<%= error_messages_for :user %> 3<% if @user.errors.any? %>
4 <div class="error_messages">
5 <ul><% @user.errors.full_messages.each do |msg| %><li><%= msg.gsub("Slug", "Title") %></li><% end %></ul>
6 </div>
7<% end %>
4 8
5<% form_for @user do |f| %> 9
10<%= form_for @user do |f| %>
6<table id="new_node"> 11<table id="new_node">
7 <tr> 12 <tr>
8 <td class="description">Login</td> 13 <td class="description">Login</td>
@@ -31,4 +36,4 @@
31 <td class="right"><%= f.submit "Update" %></td> 36 <td class="right"><%= f.submit "Update" %></td>
32 </tr> 37 </tr>
33</table> 38</table>
34<% end %> \ No newline at end of file 39<% end %>
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
index 6990c27..6beda4f 100644
--- a/app/views/users/new.html.erb
+++ b/app/views/users/new.html.erb
@@ -1,8 +1,13 @@
1<h1>Create new user</h1> 1<h1>Create new user</h1>
2 2
3<%= error_messages_for :user %> 3<% if @user.errors.any? %>
4 <div class="error_messages">
5 <ul><% @user.errors.full_messages.each do |msg| %><li><%= msg.gsub("Slug", "Title") %></li><% end %></ul>
6 </div>
7<% end %>
4 8
5<% form_for @user do |f| %> 9
10<%= form_for @user do |f| %>
6<table id="new_node"> 11<table id="new_node">
7 <tr> 12 <tr>
8 <td class="description">Login</td> 13 <td class="description">Login</td>
@@ -29,4 +34,4 @@
29 <td class="right"><%= f.submit "Create" %></td> 34 <td class="right"><%= f.submit "Create" %></td>
30 </tr> 35 </tr>
31</table> 36</table>
32<% end %> \ No newline at end of file 37<% end %>