<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>generators/sandstone/templates/controllers/audits_controller.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/helpers/audits_helper.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/functional/audits_controller_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/functional/editors_controller_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/functional/page_templates_controller_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/functional/pages_controller_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/functional/previews_controller_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/functional/sitemaps_controller_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/sandstone_test_factory.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/sandstone_test_helper.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/unit/audit_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/unit/editor_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/unit/page_template_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/test/unit/page_test.rb</filename>
    </added>
    <added>
      <filename>generators/sandstone/templates/views/audits/index.html.erb</filename>
    </added>
    <added>
      <filename>lib/sandstone/controllers/audits.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -32,9 +32,10 @@ If you want to audit editor logins, you should add +Audit.log('login', editor)+
 
 Routes
 ======
-You must add the following routes (or similar ones) to your config/routes.rb file. Note that +map.sandstone '*path'+ is a catch-all route, so if you're relying on the standard Rails default route (+':controller/:action/:id') you may have to do some more work to get Sandstone running.
+You must add the following routes (or similar ones) to your config/routes.rb file. Note that +map.sandstone '*path'+ is a catch-all route, so if you're relying on the standard Rails default route (+':controller/:action/:id'+) you may have to do some more work to get Sandstone running.
 
   map.workspace 'editor/home', :controller =&gt; 'editors', :action =&gt; 'show'
+  map.resources :audits
   map.resources :editors
   map.resources :pages
   map.resources :page_templates</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -28,47 +28,30 @@ class SandstoneGenerator &lt; Rails::Generator::Base
     template_dir = File.join(File.dirname(__FILE__), 'templates')
     
     record do |m|
-      %w(editors page_templates pages previews sitemaps).each do |system|
-
-        # Handle controllers and helpers
-        %w(controller helper).each do |area|
-          file = File.join(area.pluralize, &quot;#{system}_#{area}.rb&quot;)
-          m.file(file, File.join('app', file))
+      Dir.chdir(template_dir) do
+        
+        # handle models, controllers, helpers, and views
+        %w(models controllers helpers views).each do |area|
+          m.directory(File.join('app', area))
+          Dir.glob(File.join(area, '**', '*')).each do |file|
+            m.directory(File.join('app', file)) if File.directory?(file)
+            m.file(file, File.join('app', file)) if File.file?(file)
+          end
         end
                 
-        # Handle views
-        view_dir = File.join('views', system)
-        app_view_dir = File.join('app', view_dir)
-        
-        m.directory(app_view_dir)
-        
-        Dir.glob(File.join(template_dir, view_dir, '*')).each do |file|
-          m.file(File.join(view_dir, File.basename(file)), 
-            File.join(app_view_dir, File.basename(file)))
+        # handle tests
+        m.directory('test')
+        Dir.glob(File.join('test', '**', '*')).each do |file|
+          m.directory(file) if File.directory?(file)
+          m.file(file, file) if File.file?(file)
         end
-        
-      end
-      
-      # Handle layouts
-      m.directory(File.join('app', 'views', 'layouts'))
-      layout_dir = File.join('views', 'layouts')
-      Dir.glob(File.join(template_dir, layout_dir, '*')).each do |file|
-        m.file(File.join(layout_dir, File.basename(file)), 
-          File.join('app', layout_dir, File.basename(file)))
       end
       
-      # Handle models
-      model_dir = File.join('models')
-      Dir.glob(File.join(template_dir, model_dir, '*')).each do |file|
-        m.file(File.join(model_dir, File.basename(file)), 
-          File.join('app', 'models', File.basename(file)))
-      end
+      # Create directory for cached CMS pages
+      m.directory('app/views/pages/generated')
 
-      # Handle individual files
-      m.file(File.join('sandstone.css'),
-        File.join('app', '..', 'public', 'stylesheets', 'sandstone.css'))
-      m.file(File.join('helpers', 'sandstone_helper.rb'),
-        File.join('app', 'helpers', 'sandstone_helper.rb'))
+      # Handle CSS
+      m.file('sandstone.css', 'public/stylesheets/sandstone.css')
 
       # Handle migrations
       Dir.glob(File.join(template_dir, 'migrate', '*')).each do |file|</diff>
      <filename>generators/sandstone/sandstone_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
 module EditorsHelper
+  # TODO: incorrectly assumes presence of a User model
   def potential_editors
     User.find(:all, :select =&gt; 'id, login').map {|u| [u.login, u.id]}
   end</diff>
      <filename>generators/sandstone/templates/helpers/editors_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,27 +1,45 @@
 module PagesHelper
   include SandstoneHelper
-  
+
   def parent_pages_for(page)
     pages = Page.find(:all, :select =&gt; 'id, title').map {|p| [p.title, p.id]}
     pages.reject {|p| p[1] == page.id} unless page.new_record?
     pages
   end
-  
+
+  def editors_for(page)
+    editors = Editor.find(:all).map {|e| [e.user.name, e.id]}
+    [['none', '']] + editors
+  end
+
+  def versions_for(page)
+    versions_array = page.versions.map do |v| 
+      text = &quot;#{status_icon(v)} v#{v.version} - #{v.updated_at.to_s(:short)}&quot;
+      [text, v.version]
+    end.reverse
+    options_for_select(versions_array, page.version)
+  end
+
   def templates
-    PageTemplate.find(:all, :select =&gt; 'id, name').map {|p| [p.name, p.id]}
+    available = [['default', '']]
+    templates = PageTemplate.find(:all, :select =&gt; 'id, name').map {|p| [p.name, p.id]} 
+    available = templates.empty? ? available : available + templates
   end
-  
+
   def status_icon(page)
-    case page.status
-      when 'new'
-        '*'
-      when 'pending'
-        '-'
-      when 'published'
-        ''
+    status = case page.status
+    when 'new'
+      '*'
+    when 'pending'
+      '-'
+    when 'published'
+      ''
     end
+
+    status += 'E' if page.expires_at? &amp;&amp; page.expires_at &lt; Time.now
+    status
   end
-  
+
   def editor_link_to(page, *args)
     if editor.can_edit? page
       link_to *args
@@ -29,7 +47,7 @@ module PagesHelper
       args.first
     end
   end
-  
+
   def manager_link_to(*args)
     if editor.manager?
       link_to *args</diff>
      <filename>generators/sandstone/templates/helpers/pages_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,8 @@ class CreatePages &lt; ActiveRecord::Migration
         t.text     :content,          :null =&gt; true
         t.text     :meta_description, :null =&gt; true
         t.text     :meta_keywords,    :null =&gt; true
+        t.datetime :active_at,        :null =&gt; true
+        t.datetime :expires_at,       :null =&gt; true
         t.datetime :created_at
         t.datetime :updated_at
         t.datetime :deleted_at,       :null =&gt; true</diff>
      <filename>generators/sandstone/templates/migrate/create_pages.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,3 @@
 class Page &lt; ActiveRecord::Base
-  EXPLICIT_ROUTES = ActionController::Routing::Routes.routes.inject([]) { |array, r| array &lt;&lt; r.segments.inject(&quot;&quot;) { |str,s| str &lt;&lt; s.to_s }}
-  
   include Sandstone::Models::Page
 end
\ No newline at end of file</diff>
      <filename>generators/sandstone/templates/models/page.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,3 @@
 class PageTemplate &lt; ActiveRecord::Base
-  LAYOUT_PATH = &quot;#{File.dirname(__FILE__)}/../views/layouts&quot;
-
   include Sandstone::Models::PageTemplate
 end
\ No newline at end of file</diff>
      <filename>generators/sandstone/templates/models/page_template.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,19 +6,21 @@
   http://qvisory.org/&lt;%= f.text_field :path %&gt;
 &lt;/div&gt;
 
-&lt;% if Page.count &gt; 0 -%&gt;
+&lt;% if editor.manager? &amp;&amp; !page.new_record? -%&gt;
 &lt;div&gt;
-  &lt;label for=&quot;page_parent_id&quot;&gt;Parent Page&lt;/label&gt;
-  &lt;%= f.select :parent_id, parent_pages_for(page), :include_blank =&gt; true %&gt;
+  &lt;label for=&quot;page_editor_id&quot;&gt;Assigned To&lt;/label&gt;
+  &lt;%= f.select :editor_id, editors_for(page) %&gt;
 &lt;/div&gt;
 &lt;% end -%&gt;
 
-&lt;% if templates.size &gt; 0 -%&gt;
+&lt;div&gt;
+  &lt;label for=&quot;page_parent_id&quot;&gt;Parent Page&lt;/label&gt;
+  &lt;%= f.select :parent_id, parent_pages_for(page) %&gt;
+&lt;/div&gt;
 &lt;div&gt;
   &lt;label for=&quot;page_page_template_id&quot;&gt;Template&lt;/label&gt;
-  &lt;%= f.select :page_template_id, templates, :include_blank =&gt; true %&gt;
+  &lt;%= f.select :page_template_id, templates %&gt;
 &lt;/div&gt;
-&lt;% end -%&gt;
 
 &lt;div&gt;
   &lt;label for=&quot;page_title&quot;&gt;Title&lt;/label&gt;
@@ -48,6 +50,21 @@
 &lt;/div&gt;
 
 &lt;div class=&quot;additional-fields&quot;&gt;
+  &lt;p&gt;&lt;%= link_to_function 'manage expiration', 'new Effect.Appear(&quot;page-expiration&quot;)' %&gt;&lt;/p&gt;
+  &lt;fieldset id=&quot;page-expiration&quot; style=&quot;display:none;&quot;&gt;
+    &lt;div&gt;
+      &lt;label for=&quot;page_active_at&quot;&gt;Active at&lt;/label&gt;
+      &lt;%= f.text_field :active_at %&gt;
+    &lt;/div&gt;
+
+    &lt;div&gt;
+      &lt;label for=&quot;page_expires_at&quot;&gt;Expires at&lt;/label&gt;
+      &lt;%= f.text_field :expires_at %&gt;
+    &lt;/div&gt;
+  &lt;/fieldset&gt;
+&lt;/div&gt;
+
+&lt;div class=&quot;additional-fields&quot;&gt;
   &lt;p&gt;&lt;%= link_to_function 'edit page metadata', 'new Effect.Appear(&quot;page-metadata&quot;)' %&gt;&lt;/p&gt;
   &lt;fieldset id=&quot;page-metadata&quot; style=&quot;display:none;&quot;&gt;
     &lt;div&gt;</diff>
      <filename>generators/sandstone/templates/views/pages/_form.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 &lt;div class=&quot;versioning&quot;&gt;
   viewing version
-  &lt;%= select_tag 'version', options_for_select(@page.versions.map {|v| [&quot;v#{v.version} - #{v.updated_at.to_s(:short)}&quot;, v.version]}.reverse, @page.version),
+  &lt;%= select_tag 'version', versions_for(@page),
       :onchange =&gt; &quot;location.href = '#{edit_page_path}?version='+this.options[this.selectedIndex].value;&quot; %&gt;
 &lt;/div&gt;
 </diff>
      <filename>generators/sandstone/templates/views/pages/edit.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -8,8 +8,11 @@ module Sandstone
       end
 
       def show
-        @page = Page.find_by_path(params[:path].join('/'))
-        current = @page.versions.find_by_status('published', :order =&gt; 'version DESC') if @page
+        @page = Page.find_by_path(params[:path].join('/')) 
+        current = @page.versions.find_by_status('published', :order =&gt; 'version DESC',
+          :conditions =&gt; ['(active_at IS NULL and expires_at &gt;= ?) OR (active_at &lt;= ? AND expires_at IS NULL) OR (? BETWEEN active_at AND expires_at)', Time.now, Time.now, Time.now]
+        ) if @page
+        
         if current
           @page.revert_to(current.version)
           render :layout =&gt; @page.layout
@@ -26,7 +29,11 @@ module Sandstone
 
       def edit
         @page_title = 'Edit a Page'
-        @page.revert_to(params[:version]) if params[:version]
+        if params[:version]
+          @page.revert_to(params[:version])
+        else
+          @page.load_content_from_filesystem
+        end
       end
 
       def create
@@ -46,8 +53,10 @@ module Sandstone
 
       def update
         @page = Page.find(params[:id])
-
-        if @page.update_attributes(params[:page].merge(:editor =&gt; editor))
+        page_params = params[:page]
+        page_params.merge(:editor =&gt; editor) unless page_params[:editor_id]
+        
+        if @page.update_attributes(page_params)
           Audit.log('update', editor, @page)
 
           flash[:notice] = Page::EXPLICIT_ROUTES.include?(&quot;/#{@page.path}&quot;) ? </diff>
      <filename>lib/sandstone/controllers/pages.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,15 @@
 module Sandstone
   module Models
     module Page
+      PAGE_PATH = &quot;#{RAILS_ROOT}/app/views/pages/generated&quot;
+      EXPLICIT_ROUTES = ActionController::Routing::Routes.routes.inject([]) { |array, r| array &lt;&lt; r.segments.inject(&quot;&quot;) { |str,s| str &lt;&lt; s.to_s }}
+
       def self.included(base)
         base.class_eval do
-          after_save :retire_old_published_versions
-
+          after_save    :retire_old_published_versions
+          after_save    :create_file_on_filesystem
+          after_destroy :remove_file_from_filesystem
+          
           self.acts_as_versioned
           acts_as_tree
 
@@ -37,10 +42,32 @@ module Sandstone
         def publish=(value)
           self.status = 'published'
         end
+        
+        def load_content_from_filesystem
+          if File.exists?(page_filename)
+            filesystem_content = File.read(page_filename).chomp
+            update_attributes(:content =&gt; filesystem_content, :status =&gt; 'new') if filesystem_content != content
+          end
+        end
 
+        private
         def retire_old_published_versions
           self.versions.update_all('status = &quot;retired&quot;', ['version &lt; ? AND status = ?', self.version, 'published']) if self.status == 'published'
         end
+
+        def page_filename 
+          &quot;#{::Page::PAGE_PATH}/#{path? ? path : '_root'}.html.erb&quot;
+        end
+
+        def create_file_on_filesystem
+          File.open(page_filename, 'wb+') do |file|
+            file.puts content
+          end
+        end
+
+        def remove_file_from_filesystem
+          File.delete page_filename
+        end
       end
 
       module ClassMethods</diff>
      <filename>lib/sandstone/models/page.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,10 @@
+# TODO: refactor filesystem caching between page and page_template
+# TODO: prevent overwriting application, public, and sandstone templates
 module Sandstone
   module Models
     module PageTemplate
+      LAYOUT_PATH = &quot;#{RAILS_ROOT}/app/views/layouts&quot;
+
       def self.included(base)
         base.class_eval do
           self.acts_as_versioned
@@ -21,7 +25,7 @@ module Sandstone
       module InstanceMethods
         private
         def layout_filename 
-          &quot;#{::PageTemplate::LAYOUT_PATH}/#{name.tableize}.html.erb&quot;
+          &quot;#{::PageTemplate::LAYOUT_PATH}/#{name.underscore}.html.erb&quot;
         end
 
         def create_file_on_filesystem</diff>
      <filename>lib/sandstone/models/page_template.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+# TODO: bootstrapping task
 # desc &quot;Explaining what the task does&quot;
 # task :sandstone do
 #   # Task goes here</diff>
      <filename>tasks/sandstone_tasks.rake</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>test/audit_test.rb</filename>
    </removed>
    <removed>
      <filename>test/editor_test.rb</filename>
    </removed>
    <removed>
      <filename>test/factory/audit.rb</filename>
    </removed>
    <removed>
      <filename>test/factory/editor.rb</filename>
    </removed>
    <removed>
      <filename>test/factory/page.rb</filename>
    </removed>
    <removed>
      <filename>test/factory/page_template.rb</filename>
    </removed>
    <removed>
      <filename>test/factory/user.rb</filename>
    </removed>
    <removed>
      <filename>test/page_template_test.rb</filename>
    </removed>
    <removed>
      <filename>test/page_test.rb</filename>
    </removed>
    <removed>
      <filename>test/sandstone_test.rb</filename>
    </removed>
    <removed>
      <filename>test_helper.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>2e8ce9ca80893ad1b580641f753a6b58e90c423b</id>
    </parent>
  </parents>
  <author>
    <name>ben</name>
    <email>ben@e959a6d6-1924-0410-92b3-a6fa492f4c66</email>
  </author>
  <url>http://github.com/vigetlabs/sandstone/commit/390f0152826649860aa0cf923ae3c0d81c4b1a5d</url>
  <id>390f0152826649860aa0cf923ae3c0d81c4b1a5d</id>
  <committed-date>2007-09-26T10:58:57-07:00</committed-date>
  <authored-date>2007-09-26T10:58:57-07:00</authored-date>
  <message>added audits, generate tests

git-svn-id: http://svn.extendviget.com/lab/trunk/plugins/sandstone@369 e959a6d6-1924-0410-92b3-a6fa492f4c66</message>
  <tree>1da6a58d9ccd24aa10b60423d612271634aa64e7</tree>
  <committer>
    <name>ben</name>
    <email>ben@e959a6d6-1924-0410-92b3-a6fa492f4c66</email>
  </committer>
</commit>
