qcms 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +14 -0
  2. data/README +70 -0
  3. data/Rakefile +39 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/admin/admin_controller.rb +12 -0
  6. data/app/controllers/admin/documents_controller.rb +133 -0
  7. data/app/controllers/admin/meta_definitions_controller.rb +36 -0
  8. data/app/controllers/documents_controller.rb +187 -0
  9. data/app/controllers/sendmail_controller.rb +87 -0
  10. data/app/helpers/admin/documents_helper.rb +71 -0
  11. data/app/helpers/documents_helper.rb +30 -0
  12. data/app/helpers/sendmail_helper.rb +2 -0
  13. data/app/models/document.rb +292 -0
  14. data/app/models/document_mailer.rb +13 -0
  15. data/app/models/document_sweeper.rb +28 -0
  16. data/app/models/meta_definition.rb +57 -0
  17. data/app/models/sendmail.rb +18 -0
  18. data/app/views/admin/admin/system.html.erb +34 -0
  19. data/app/views/admin/documents/_form.html.erb +60 -0
  20. data/app/views/admin/documents/default.edit.html.erb +10 -0
  21. data/app/views/admin/documents/default.new.html.erb +10 -0
  22. data/app/views/admin/documents/default.show.html.erb +77 -0
  23. data/app/views/admin/documents/index.html.erb +32 -0
  24. data/app/views/admin/documents/shared/_resource_link.html.erb +6 -0
  25. data/app/views/document_mailer/new_document.erb +12 -0
  26. data/app/views/layouts/admin.html.erb +43 -0
  27. data/app/views/layouts/application.html.erb +44 -0
  28. data/app/views/pages/404.html.erb +28 -0
  29. data/app/views/pages/contact.html.erb +42 -0
  30. data/app/views/pages/default.html.erb +12 -0
  31. data/app/views/pages/feed.rss.builder +17 -0
  32. data/app/views/pages/home.html.erb +5 -0
  33. data/app/views/pages/search.html.erb +19 -0
  34. data/app/views/pages/shared/_archived_pages.erb +16 -0
  35. data/app/views/pages/shared/_related_pages.html.erb +13 -0
  36. data/app/views/pages/sitemap.html.erb +9 -0
  37. data/app/views/pages/template.erb +51 -0
  38. data/app/views/pages/thank_you.html.erb +1 -0
  39. data/app/views/sendmail/default.erb +12 -0
  40. data/config/sitemap.example.yml +39 -0
  41. data/db/migrate/20090824150210_create_documents.rb +37 -0
  42. data/db/migrate/20091208124512_create_meta_definition.rb +26 -0
  43. data/init.rb +1 -0
  44. data/install.rb +1 -0
  45. data/lib/qcms.rb +4 -0
  46. data/lib/tasks/cms.rake +237 -0
  47. data/qcms.gemspec +91 -0
  48. data/rails/init.rb +3 -0
  49. data/tasks/qcms_tasks.rake +223 -0
  50. data/test/qwerty_test.rb +8 -0
  51. data/test/test_helper.rb +3 -0
  52. data/uninstall.rb +1 -0
  53. metadata +107 -0
@@ -0,0 +1,13 @@
1
+ class DocumentMailer < ActionMailer::Base
2
+
3
+ def new_document(document)
4
+ subject "[#{Settings.site.name}] New #{document.label}"
5
+ from Settings.mailer.from
6
+ recipients User.all.select { |u| u.has_role? 'admin'}.collect { |u| u.email }.join(', ')
7
+ body :document => document
8
+ content_type "text/html"
9
+ end
10
+
11
+
12
+
13
+ end
@@ -0,0 +1,28 @@
1
+ class DocumentSweeper < ActionController::Caching::Sweeper
2
+ observe Document
3
+
4
+ def after_save(document)
5
+ clear_document_cache(document)
6
+ end
7
+
8
+ def after_destroy(document)
9
+ clear_document_cache(document)
10
+ end
11
+
12
+ # We dont need to expire the cache for the parent as a document always
13
+ # touches its parent after_save, which will cause this method to be run
14
+ # for the parent as well.
15
+
16
+ def clear_document_cache(document)
17
+ expire_fragment :recent_posts
18
+ expire_fragment :menu
19
+
20
+ cache_paths = []
21
+ cache_paths << File.join(RAILS_ROOT, 'public', 'cache', document.path)
22
+
23
+ cache_paths.each do | cache_path |
24
+ Rails.logger.debug 'Deleting CACHE: ' + cache_path
25
+ FileUtils.rm_rf cache_path if File.exists? cache_path
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,57 @@
1
+ class MetaDefinition < ActiveRecord::Base
2
+ has_many :documents, :dependent => :destroy
3
+
4
+ validates_presence_of :label_path, :label
5
+ validates_uniqueness_of :label_path
6
+
7
+ acts_as_list
8
+ acts_as_tree
9
+ path_finder :uid => 'label', :column => 'label_path'
10
+
11
+ default_scope :order => 'position DESC'
12
+
13
+ named_scope :by_label, lambda { |label| { :conditions => ['label = ?', label] } }
14
+
15
+ before_save :nullify_empty_columns
16
+
17
+ serialize :autherisation, Hash
18
+ serialize :field_map, Hash
19
+ serialize :flash_messages, Hash
20
+
21
+
22
+ def autherisation
23
+ super || {}
24
+ end
25
+
26
+ def field_map
27
+ super || {}
28
+ end
29
+
30
+ def flash_messages
31
+ super || {}
32
+ end
33
+
34
+
35
+ def allowed?(user, action)
36
+ tokens = (autherisation[action] || Settings.documents.autherisation.send(action)).split(' ')
37
+ tokens.each do | token |
38
+ return true if token == 'all'
39
+ return true if token == 'author' && self.author == user
40
+ return true if user.has_role? token
41
+ end
42
+ false
43
+ end
44
+
45
+ # Used to find template named after label_path
46
+ # eg. blog.post.html.erb
47
+ def template_filename(include_extension = true)
48
+ label_path.gsub('/', '.') + (include_extension ? '.html.erb' : '')
49
+ end
50
+
51
+ private
52
+
53
+ # Prevent empty strings being saved
54
+ def nullify_empty_columns
55
+ %w(sort_by per_page).each { |column| self.send(column+'=', nil) if self.send(column) == '' }
56
+ end
57
+ end
@@ -0,0 +1,18 @@
1
+ class Sendmail < ActionMailer::Base
2
+
3
+ def form(params, meta, template)
4
+ subject meta[:subject]
5
+ from set_from(params, meta)
6
+ recipients meta[:recipients]
7
+ body :data => params
8
+ content_type "text/html"
9
+ template template
10
+ end
11
+
12
+ private
13
+
14
+ def set_from(params, meta)
15
+ params[:email].nil? ? params[:email] : meta[:from]
16
+ end
17
+
18
+ end
@@ -0,0 +1,34 @@
1
+ <style>
2
+ ul.info li { margin-left: 20px;
3
+ list-style: none;
4
+ padding: 5px;
5
+ background-color: #CFDBA0;
6
+ margin-bottom: 4px;
7
+ }
8
+ </style>
9
+
10
+ <h3>Qwerty</h3>
11
+ <ul class="info">
12
+ <li>Qcore: <%= Qcore::VERSION %></li>
13
+ <li>Qcms: <%= Qcms::VERSION %></li>
14
+ </ul>
15
+
16
+ <h3>Rails</h3>
17
+ <ul class="info">
18
+ <li>Version: <%= Rails.version %></li>
19
+ <li>User: <%= Etc.getpwuid(Process.euid).name %></li>
20
+ <li>Root: <%= RAILS_ROOT %></li>
21
+ <li>Env: <%= RAILS_ENV %></li>
22
+ </ul>
23
+
24
+ <h3>Gem</h3>
25
+ <ul class="info">
26
+ <li>Config: <%= Gem.config_file %></li>
27
+ <li>Default path: <%= Gem.default_path %></li>
28
+ </ul>
29
+
30
+ <h3>Ruby</h3>
31
+ <ul class="info">
32
+ <li>version <%= Gem.ruby_version.to_s %></li>
33
+ <li>path <%= Gem.ruby %></li>
34
+ </ul>
@@ -0,0 +1,60 @@
1
+ <p>Title<BR/>
2
+ <%= f.text_field :title %>
3
+ </p>
4
+
5
+ <p>Permalink<BR/>
6
+ <% if @document.new_record? %>
7
+ <%= f.text_field :permalink, :value => '' %>
8
+ <small>This will be generated automatically if left blank</small>
9
+ <% else %>
10
+ <%= f.text_field :permalink, :readonly => 'true' %>
11
+ <small>Not editable</small>
12
+ <% end %>
13
+ </p>
14
+
15
+ <p>State<BR/>
16
+ <%= f.select :state, [['Published','published'], ['Draft', 'draft']] %>
17
+ </p>
18
+
19
+ <p>Published <BR><%= f.date_select :published_at, :order => [:day, :month, :year] %></p>
20
+
21
+ <p>Body<BR/>
22
+ <%= f.text_area :body %>
23
+ </p>
24
+
25
+ <p>Summary<BR/>
26
+ <%= f.text_field :summary %>
27
+ <small>This will be generated automatically if left blank</small>
28
+ </p>
29
+
30
+ <p>Image<BR/>
31
+ <%= f.file_field :resource %>
32
+ <%= render :partial => 'admin/documents/shared/resource_link' %>
33
+ <% if @document.resource.exists? %>
34
+ <div>Delete image: <%= f.check_box :delete_resource %></div>
35
+ <% end %>
36
+ </p>
37
+
38
+ <p>
39
+ Image Description<br/>
40
+ <%= f.text_field :resource_description %>
41
+ </p>
42
+
43
+ <fieldset>
44
+ <legend>Meta</legend>
45
+ <p>Page Title<BR/>
46
+ <%= f.text_field :meta_title %>
47
+ </p>
48
+
49
+ <p>Description<BR/>
50
+ <%= f.text_field :meta_description %>
51
+ </p>
52
+
53
+ <p>Keywords<BR/>
54
+ <%= f.text_field :meta_keywords %>
55
+ </p>
56
+ </fieldset>
57
+
58
+ <%= f.hidden_field :parent_id %>
59
+ <%= f.hidden_field :label %>
60
+ <%= f.hidden_field :meta_definition_id %>
@@ -0,0 +1,10 @@
1
+ <h4>Edit <%= @document.label.titleize %></h4>
2
+ <%= error_messages_for :document %>
3
+ <% form_for @document.becomes(Document), :url => admin_document_path(@document.id), :html => { :multipart => true } do |f| %>
4
+ <%= render :partial => form_partial, :locals => { :f => f } %>
5
+ <%= f.submit 'Save' %> or <%= link_to 'Cancel', admin_cancel_document_path(@document), :class => 'button' %>
6
+ <% end %>
7
+
8
+ <% if session[:system] %>
9
+ <%= form_partial %>
10
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <h4>New <%= @document.label.titleize %></h4>
2
+ <%= error_messages_for :document %>
3
+ <% form_for @document.becomes(Document), :url => admin_documents_path, :html => { :multipart => true } do |f| %>
4
+ <%= render :partial => form_partial, :locals => { :f => f } %>
5
+ <%= f.submit 'Save' %> or <%= link_to 'Cancel', admin_cancel_document_path(@document), :class => 'button' %>
6
+ <% end %>
7
+
8
+ <% if session[:system] %>
9
+ <%= form_partial %>
10
+ <% end %>
@@ -0,0 +1,77 @@
1
+ <h4><%= @document.title %></h4>
2
+
3
+ <div style="margin-bottom: 20px;"><%= textilize @document.summary %></div>
4
+
5
+ <% @document.meta_definition.children.each do |md| %>
6
+
7
+ <h4 style="margin-top: 20px; border-bottom: 1px solid #ADBCBC;"><%= md.label.titleize.pluralize.capitalize %></h4>
8
+
9
+ <% unless md.documents.empty? %>
10
+ <table>
11
+ <tr>
12
+ <% md.field_map.each do |k,v| %>
13
+ <td><%= k.titleize %></td>
14
+ <% end %>
15
+ <th>Title</th>
16
+ <th>State</th>
17
+ <th>Author</th>
18
+ <% if md.record_hits? %>
19
+ <th>Hits</th>
20
+ <% end %>
21
+ </tr>
22
+ <% documents = @document.children.by_label(md.label).order_by(md.sort_by).paginate(:per_page => 20, :page => params["#{md.label}_page".to_sym]) %>
23
+ <% documents.each do |page| %>
24
+ <tr>
25
+ <% md.field_map.each do |k,v| %>
26
+ <td><%= page.send(v) %></td>
27
+ <% end %>
28
+ <td><%= truncate(page.title, :length => 40) %></td>
29
+ <td>
30
+ <% form_for page.becomes(Document), :url => admin_document_path(page.id) do |f| %>
31
+ <%= f.select :state, [['Published','published'], ['Draft', 'draft'], ['Pending', 'pending']] %>
32
+ <%= f.submit 'Change' %>
33
+ <% end %>
34
+ </td>
35
+ <td><%= page.author.name %></td>
36
+ <% if md.record_hits? %>
37
+ <td><%= page.hits %></td>
38
+ <% end %>
39
+ <td>
40
+ <%= link_to 'Open', admin_document_path(page.id), :class => 'button' %>
41
+ </td>
42
+ <td><%= link_to 'Edit', edit_admin_document_path(page.id), :class => 'button' %></td>
43
+ <% if md.sort_by == 'position ASC' %>
44
+ <td>
45
+ <%= link_to 'Up', up_admin_document_path(page.id), :class => 'button' unless page.first? %>
46
+ <%= link_to 'Down', down_admin_document_path(page.id), :class => 'button' unless page.last? %>
47
+ </td>
48
+ <% end %>
49
+ <td>
50
+ <% unless page.system? %>
51
+ <%= link_to 'Delete', admin_document_path(page.id), :method => 'delete', :confirm => 'Are you sure?', :class => 'button' %>
52
+ <% end %>
53
+ </td>
54
+ </tr>
55
+ <% end %>
56
+ </table>
57
+ <%= will_paginate documents, :param_name => "#{md.label}_page".to_sym %>
58
+ <% else %>
59
+ <p>There are no <%= md.label.titleize.pluralize %> yet!</p>
60
+ <% end %>
61
+ <p><%= link_to 'New ', new_admin_document_path + '?parent=' + @document.id.to_s + '&label=' + md.label, :class => 'button' %></p>
62
+
63
+ <% form_for md, :url => admin_meta_definition_path(md.id) do | f | %>
64
+ <p><label>Sort by</label> <%= f.select :sort_by, sort_by_options, :include_blank => true %></p>
65
+ <p><label>Per page</label> <%= f.select :per_page, per_page_options, :include_blank => true %></p>
66
+ <input type="hidden" name="document_id" value ="<%= @document.id %>" />
67
+ <%= f.submit 'Save' %>
68
+ <% end %>
69
+ <% end %>
70
+
71
+
72
+
73
+ <style>
74
+ form.edit_meta_definition { font-size: 1em; }
75
+ </style>
76
+
77
+
@@ -0,0 +1,32 @@
1
+ <h2>Sections</h2>
2
+
3
+ <table>
4
+ <tr>
5
+ <th>Title</th>
6
+ <th></th>
7
+ <th></th>
8
+ </tr>
9
+ <% @documents.each do |document| %>
10
+ <tr>
11
+ <td>
12
+ <%= document.title %><br />
13
+ <small><%= truncate(document.summary, :length => 30) %></small>
14
+ </td>
15
+ <td>
16
+ <a href="<%= admin_document_path(document.id) %>" class="button">Open</a>
17
+ </td>
18
+ <td><a href="<%= edit_admin_document_path(document.id) %>" class="button">Edit</a></td>
19
+ <td><a href="<%= new_admin_document_path + '?parent_id=' + document.id.to_s %>" class="button">Add</a></td>
20
+ <td>
21
+ <%= link_to 'Up', up_admin_document_path(document.id), :class => 'button' unless document.first? %>
22
+ <%= link_to 'Down', down_admin_document_path(document.id), :class => 'button' unless document.last? %>
23
+ </td>
24
+ <td><%= link_to 'Delete', admin_document_path(document.id), :method => 'delete', :class => 'button' %></td>
25
+ <td><a href="<%= document_path(document) %>" class="button">Live</a></td>
26
+ </tr>
27
+ <% end %>
28
+ </table>
29
+
30
+ <p><%= link_to 'New Page', new_admin_document_path + '?label_path=page', :class => 'button' %>
31
+
32
+
@@ -0,0 +1,6 @@
1
+ <% resource ||= @document.resource if @document -%>
2
+ <% if resource.exists? %>
3
+ <p>Already uploaded: <a href="<%= resource.url %>"><%= resource.original_filename %></a></p>
4
+ <% else %>
5
+ <p>Nothing uploaded yet!</p>
6
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <p>You have a new <%= @document.label %></p>
2
+
3
+ <% unless @document.published? %>
4
+ <p>This <%= @document.label %> is currently <%= @document.state.capitalize %></p>
5
+ <% end %>
6
+
7
+ <p><%= link_to 'Edit', 'http://' + Settings.domain + admin_document_path(@document.parent_id) %></p>
8
+
9
+
10
+
11
+
12
+
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
4
+ <head>
5
+ <title><%= @page_title || 'untitled' %></title>
6
+ <meta http-equiv="content-type" content="text/xhtml; charset=utf-8" />
7
+ <link rel="stylesheet" href="/stylesheets/admin/styles.css" type="text/css" media="screen" />
8
+ <%= javascript_include_tag 'jquery-1.3.1.min.js' %>
9
+ <%= javascript_include_tag 'application' %>
10
+ <%= meta_tags -%>
11
+ <%= yield :head %>
12
+ </head>
13
+ <body>
14
+
15
+ <% if flash[:notice] %>
16
+ <div id="flash-notice"><%= flash[:notice] %> <a href="#">Close</a></div>
17
+ <% end %>
18
+
19
+ <div id="header">QWERTY+ Control Panel</div>
20
+
21
+ <ul id="top_menu">
22
+ <li><a href="<%= admin_dashboard_path %>">Dashboard</a></li>
23
+ <li><a href="<%= admin_users_path %>">Users</a></li>
24
+ <li><a href="<%= root_path %>">Site Homepage</a></li>
25
+ </ul>
26
+
27
+ <% if @document %>
28
+ <%= admin_bread_crumb(@document) %>
29
+ <% end %>
30
+
31
+ <div id="container">
32
+
33
+ <div id="content">
34
+ <%= yield %>
35
+ </div>
36
+
37
+ <div id="sidebar">
38
+ <%= yield :sidebar %>
39
+ </div>
40
+
41
+ </div> <!-- container -->
42
+ </body>
43
+ </html>
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
4
+ <head>
5
+ <title><%= page_title %></title>
6
+ <meta http-equiv="content-type" content="text/xhtml; charset=utf-8" />
7
+ <link rel="stylesheet" href="/stylesheets/styles.css" type="text/css" media="screen" />
8
+ <%= javascript_include_tag 'jquery-1.3.1.min.js' %>
9
+ <%= javascript_include_tag 'application' %>
10
+ <%= meta_tags -%>
11
+ <%= yield :head %>
12
+ </head>
13
+ <body>
14
+ <div id="user_nav">
15
+ <% if current_user %>
16
+ <a href="<%= logout_path %>">Logout</a>
17
+ <a href="/admin">Admin</a>
18
+ <% else %>
19
+ <a href="<%= login_path %>">Login</a>
20
+ <% end %>
21
+ </div>
22
+
23
+ <% if flash[:notice] %>
24
+ <div id="flash-notice"><%= flash[:notice] %> <a href="#">Close</a></div>
25
+ <% end %>
26
+
27
+ <div id="header"></div>
28
+ <ul id="nav">
29
+ <% Document.public.roots.order_by('position').each do | doc | %>
30
+ <li style=""><a href="<%= document_path(doc) %>"><%= doc.title %></a></li>
31
+ <% end %>
32
+ </ul>
33
+ <div style="clear:both;"></div>
34
+ <div id="container">
35
+ <div id="content">
36
+ <%= yield %>
37
+ </div>
38
+
39
+ <div id="sidebar">
40
+ <%= yield :sidebar %>
41
+ </div>
42
+ </div> <!-- container -->
43
+ </body>
44
+ </html>