diff --git a/app/controllers/application.rb b/app/controllers/application.rb index 245c4c7..6728b6b 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -29,6 +29,14 @@ class ApplicationController < ActionController::Base end end + ## + # Sets the @page variable to allow discussions. This should probably + # have some kind of permission availability check later on. + # + def allow_page_discussions + @page.allow_discussions = true + end + private ## diff --git a/app/controllers/beers_controller.rb b/app/controllers/beers_controller.rb index 184d7b7..bc89bc8 100644 --- a/app/controllers/beers_controller.rb +++ b/app/controllers/beers_controller.rb @@ -43,6 +43,7 @@ class BeersController < ApplicationController @beer = Beer.new(params[:beer]) @page = Page.new(params[:page]) @beer.page = @page + allow_page_discussions brewery = Brewery.find_by_title(params[:brewery][:title]) rescue nil @beer.brewery = brewery respond_to do |format| diff --git a/app/controllers/breweries_controller.rb b/app/controllers/breweries_controller.rb index 73c35dc..18aff98 100644 --- a/app/controllers/breweries_controller.rb +++ b/app/controllers/breweries_controller.rb @@ -40,7 +40,7 @@ class BreweriesController < ApplicationController @brewery = Brewery.new(params[:brewery]) @page = Page.new(params[:page]) @brewery.page = @page - + allow_page_discussions respond_to do |format| if @brewery.save flash[:notice] = 'Brewery was successfully created.' diff --git a/app/controllers/discussions_controller.rb b/app/controllers/discussions_controller.rb index b772c94..66606f6 100644 --- a/app/controllers/discussions_controller.rb +++ b/app/controllers/discussions_controller.rb @@ -1,79 +1,73 @@ class DiscussionsController < ApplicationController + append_before_filter :ensure_xhr, :only => [ :allow_discussions, + :deny_discussions ] + # GET /discussions # GET /discussions.xml def index - @discussions = Discussion.find(:all) - + @content_title = 'Discussion Topics' + @secondary_title = 'All discussion topics' + @pages, @wiki_pages = paginate :pages, :order => 'title ASC', + :conditions => [ 'allow_discussions = ?', true ], :per_page => 25, + :include => [ 'discussions' ] respond_to do |format| format.html # index.rhtml - format.xml { render :xml => @discussions.to_xml } end end - + # GET /discussions/1 # GET /discussions/1.xml def show - @discussion = Discussion.find(params[:id]) - + @page = Page.find(params[:id], :include => [ 'discussions' ]) + @secondary_title = @page.title + @pages, @discussions = paginate :discussion, :order => 'created_at ASC', + :conditions => [ 'page_id = ?', @page.id ], :per_page => 25 respond_to do |format| format.html # show.rhtml - format.xml { render :xml => @discussion.to_xml } + format.xml { render :xml => @discussions.to_xml } end end - - # GET /discussions/new - def new - @discussion = Discussion.new - end - - # GET /discussions/1;edit - def edit - @discussion = Discussion.find(params[:id]) - end - + # POST /discussions # POST /discussions.xml def create @discussion = Discussion.new(params[:discussion]) - - respond_to do |format| - if @discussion.save - flash[:notice] = 'Discussion was successfully created.' - format.html { redirect_to discussion_url(@discussion) } - format.xml { head :created, :location => discussion_url(@discussion) } - else - format.html { render :action => "new" } - format.xml { render :xml => @discussion.errors.to_xml } - end + if @discussion.save + render :partial => 'discussion', + :locals => { + :discussion => @discussion, + :li_number => @discussion.page.discussions.size + } + else + render :xml => @discussion.errors.to_xml, :status => 500 end end - + # PUT /discussions/1 # PUT /discussions/1.xml def update @discussion = Discussion.find(params[:id]) - - respond_to do |format| - if @discussion.update_attributes(params[:discussion]) - flash[:notice] = 'Discussion was successfully updated.' - format.html { redirect_to discussion_url(@discussion) } - format.xml { head :ok } - else - format.html { render :action => "edit" } - format.xml { render :xml => @discussion.errors.to_xml } - end + if @discussion.update_attributes(params[:discussion]) + head :ok + else + render :xml => @discussion.errors.to_xml end end - + # DELETE /discussions/1 # DELETE /discussions/1.xml def destroy @discussion = Discussion.find(params[:id]) @discussion.destroy - - respond_to do |format| - format.html { redirect_to discussions_url } - format.xml { head :ok } - end + head :ok + end + + ## + # Forces an allow of Discussion models on a Page. + # + def allow_discussions + @page = Page.find(params[:id]) + status = 500 + end end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 01b5920..046981a 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -42,6 +42,7 @@ class PagesController < ApplicationController # POST /pages.xml def create @page = Page.new params[:page] + allow_page_discussions respond_to do |format| if @page.save flash[:notice] = 'Page was successfully created.' diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f54e35a..355e4e7 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -10,7 +10,7 @@ module ApplicationHelper # Returns a pretty name for the current chunk. # def content_title - return @content_title if @content_title + return h(@content_title) if @content_title controller.class.to_s.gsub(/Controller/, '') end @@ -19,7 +19,7 @@ module ApplicationHelper # action in the controller. # def secondary_title - return @secondary_title if @secondary_title + return h(@secondary_title) if @secondary_title params[:action].to_s.capitalize.gsub(/_/) do |x| $1.capitalize end @@ -29,6 +29,21 @@ module ApplicationHelper # Returns a link for a Page model. # def link_to_page(page) - link_to page.title, page_path({ :id => page.title_for_url }) + link_to h(page.title), page_path({ :id => page.title_for_url }) + end + + ## + # Helper to set the allow_discussions field in the Page model. + # + def allow_page_discussions + @page.allow_discussions = true + end + + ## + # Helper to check if Discussion is allowed. This should check the underlying + # permissions first instead of looking in the model. + # + def discussions_allowed? + @page and @page.allow_discussions? end end diff --git a/app/helpers/discussions_helper.rb b/app/helpers/discussions_helper.rb index 46c02d0..80c7bcd 100644 --- a/app/helpers/discussions_helper.rb +++ b/app/helpers/discussions_helper.rb @@ -1,2 +1,12 @@ module DiscussionsHelper + ## + # Returns a link to a Page model or to the Page owner if applicable. + # + def page_or_parent_link(page) + if page.owner_type.to_s.empty? + return link_to 'Show Wiki Page', page_path(page.title_for_url) + end + link_to("Show #{page.owner_type} Page", + send("#{page.owner_type.downcase}_path", page.title_for_url)) + end end diff --git a/app/models/discussion.rb b/app/models/discussion.rb index 52513ad..c1d75c0 100644 --- a/app/models/discussion.rb +++ b/app/models/discussion.rb @@ -1,2 +1,6 @@ +## +# This model will hold all forum and comment type chunks of text for a Page. +# class Discussion < ActiveRecord::Base + belongs_to :page end diff --git a/app/models/page.rb b/app/models/page.rb index ff0cbab..02c0a3a 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -15,12 +15,17 @@ class Page < ActiveRecord::Base acts_as_taggable belongs_to :owner, :polymorphic => true + has_many :discussions, :order => 'discussions.created_at ASC', + :dependent => :destroy + validates_presence_of :title validates_uniqueness_of :title, :scope => 'owner_type' validates_format_of :title, :with => /^([A-Za-z0-9 ])+$/, :message => 'may only contain letters, numbers and spaces' before_save :update_html + attr_protected :allow_discussions + ## # Returns an url-friendly title for making links. # diff --git a/app/views/discussions/_discussion.rhtml b/app/views/discussions/_discussion.rhtml new file mode 100644 index 0000000..e9b7587 --- /dev/null +++ b/app/views/discussions/_discussion.rhtml @@ -0,0 +1,9 @@ +
  • value="<%= li_number -%>"<% end -%>> +
    + Author Goes Here +

    Posted <%= distance_of_time_in_words discussion.created_at, Time.now rescue 'xxx' %> ago.

    +
    +
    + <%= h(discussion.text) %> +
    +
  • \ No newline at end of file diff --git a/app/views/discussions/_discussion_form.rhtml b/app/views/discussions/_discussion_form.rhtml new file mode 100644 index 0000000..5140149 --- /dev/null +++ b/app/views/discussions/_discussion_form.rhtml @@ -0,0 +1,26 @@ +
    + <%= error_messages_for :discussion %> +
    + +<%= form_remote_tag :url => discussions_path, + :update => { :success => 'comments', :failure => 'comment_errors' }, + :position => 'bottom', + :loading => "Element.show('spinner'); Element.hide('preview')", + :complete => "Element.hide('spinner'); $('discussion_form').elements['discussion_text'].value = ''; new Effect.Highlight('comments', {duration:0.75})", + :html => { :id => 'discussion_form', :class => 'discussions' } %> +<%= hidden_field_tag 'discussion[page_id]', @page.id %> +
    +

    Discuss

    +

    + +

    + +

    + <%= submit_tag 'Submit' %> + <%= image_tag '/images/spinner.gif', :id => 'spinner', :style => 'display:none' %> +

    +
    + diff --git a/app/views/discussions/edit.rhtml b/app/views/discussions/edit.rhtml deleted file mode 100644 index 60358f6..0000000 --- a/app/views/discussions/edit.rhtml +++ /dev/null @@ -1,12 +0,0 @@ -

    Editing discussion

    - -<%= error_messages_for :discussion %> - -<% form_for(:discussion, :url => discussion_path(@discussion), :html => { :method => :put }) do |f| %> -

    - <%= submit_tag "Update" %> -

    -<% end %> - -<%= link_to 'Show', discussion_path(@discussion) %> | -<%= link_to 'Back', discussions_path %> \ No newline at end of file diff --git a/app/views/discussions/index.rhtml b/app/views/discussions/index.rhtml index 96ec4ad..3e8f33f 100644 --- a/app/views/discussions/index.rhtml +++ b/app/views/discussions/index.rhtml @@ -1,18 +1,10 @@ -

    Listing discussions

    - - - - - -<% for discussion in @discussions %> - - - - - +<% unless @wiki_pages.empty? -%> +
    <%= link_to 'Show', discussion_path(discussion) %><%= link_to 'Edit', edit_discussion_path(discussion) %><%= link_to 'Destroy', discussion_path(discussion), :confirm => 'Are you sure?', :method => :delete %>
    - -
    - -<%= link_to 'New discussion', new_discussion_path %> \ No newline at end of file + +<%= render :partial => 'shared/pagination_links' %> +<% end -%> diff --git a/app/views/discussions/new.rhtml b/app/views/discussions/new.rhtml deleted file mode 100644 index 1c6df63..0000000 --- a/app/views/discussions/new.rhtml +++ /dev/null @@ -1,11 +0,0 @@ -

    New discussion

    - -<%= error_messages_for :discussion %> - -<% form_for(:discussion, :url => discussions_path) do |f| %> -

    - <%= submit_tag "Create" %> -

    -<% end %> - -<%= link_to 'Back', discussions_path %> \ No newline at end of file diff --git a/app/views/discussions/show.rhtml b/app/views/discussions/show.rhtml index c2862c1..3bdf125 100644 --- a/app/views/discussions/show.rhtml +++ b/app/views/discussions/show.rhtml @@ -1,3 +1,15 @@ +<%= render :partial => 'pages/page' %> -<%= link_to 'Edit', edit_discussion_path(@discussion) %> | -<%= link_to 'Back', discussions_path %> \ No newline at end of file +
      + <%= render :partial => 'discussion', :collection => @discussions %> +
    + +<%= render :partial => 'shared/pagination_links' %> + +<% if @page.allow_discussions? -%> + <%= render :partial => 'discussion_form' %> +<% end -%> + +<% content_for 'sidebar' do -%> + <%= page_or_parent_link(@page) -%>
    +<% end -%> \ No newline at end of file diff --git a/app/views/layouts/application.rhtml b/app/views/layouts/application.rhtml index f490f19..e7bd882 100644 --- a/app/views/layouts/application.rhtml +++ b/app/views/layouts/application.rhtml @@ -31,6 +31,7 @@ <%= link_to_unless_current 'Browse The Beer Wiki', pages_path -%>
    <%= link_to_unless_current 'Browse Beers', beers_path -%>
    <%= link_to_unless_current 'Browse Breweries', breweries_path -%>
    + <%= link_to_unless_current 'Discussions', discussions_path -%>

    <%= yield :sidebar %> diff --git a/app/views/pages/_page.rhtml b/app/views/pages/_page.rhtml index 3bb911b..7e03223 100644 --- a/app/views/pages/_page.rhtml +++ b/app/views/pages/_page.rhtml @@ -2,7 +2,6 @@

    <%= @page.title %> - <% unless simple -%>Comment Size Here<% end -%>

    <% unless simple -%>
    Posted by Author Name Here @@ -19,3 +18,9 @@ <% end if @page.owner and @page.owner.respond_to?("page_attributes") %> <% end -%>
    + +<% content_for 'sidebar' do -%> + <% if @page.allow_discussions? or !@page.discussions.empty? -%> + <%= link_to "Discuss (#{@page.discussions.size})", discussion_path(@page) -%>
    + <% end -%> +<% end -%> \ No newline at end of file diff --git a/app/views/pages/_page_form.rhtml b/app/views/pages/_page_form.rhtml index a7803ca..0cc1dd8 100644 --- a/app/views/pages/_page_form.rhtml +++ b/app/views/pages/_page_form.rhtml @@ -1,6 +1,7 @@

    <%= text_area 'page', 'redcloth' %>

    +

    <%= content_tag('small', link_to("Textile enabled", "http://hobix.com/textile/")) %>

    <%= text_field 'page', 'tag_names' %> -

    +

    \ No newline at end of file diff --git a/db/migrate/006_create_discussions.rb b/db/migrate/006_create_discussions.rb index 1d1fc9c..2069639 100644 --- a/db/migrate/006_create_discussions.rb +++ b/db/migrate/006_create_discussions.rb @@ -3,10 +3,15 @@ class CreateDiscussions < ActiveRecord::Migration create_table :discussions do |t| t.column :page_id, :integer t.column :text, :text + t.column :created_at, :timestamp end + add_column :pages, :allow_discussions, :boolean, :default => false + add_column :page_versions, :allow_discussions, :boolean, :default => false end def self.down drop_table :discussions + remove_column :pages, :allow_discussions + remove_column :page_versions, :allow_discussions end end diff --git a/public/stylesheets/content.css b/public/stylesheets/content.css index 62fb329..e6439fb 100644 --- a/public/stylesheets/content.css +++ b/public/stylesheets/content.css @@ -190,70 +190,65 @@ /* Comments and Trackbacks */ -#content ol.comments, -#content ol.trackbacks { +#content ol.discussions { list-style-type: none; margin: 0; padding: 0; } -#content li.comment, -#content li.trackback { +#content li.discussion { border: 2px solid #ddd; margin: 0 0 1.5em; padding: 1em; } -#content li.comment.preview { +#content li.discussion.preview { background: #ffc; border: 3px solid #fab444; margin: 0 0 1.5em; padding: 1em; } -#content li.comment .author, -#content li.trackback .author { +#content li.discussion .author { font-weight: bold; margin-bottom: 1em; } -#content li.comment .author cite, -#content li.trackback .author cite { +#content li.discussion .author cite { font-size: 16px; letter-spacing: -1px; } -#content li.comment .author abbr, -#content li.trackback .author abbr { color: #999; } +#content li.discussion .author abbr { color: #999; } -#content li.comment .author .gravatar { +#content li.discussion .author .gravatar { margin: 0 0 0.5em 0.5em; float: right; } -#content li.comment .author div { +#content li.discussion .author div { margin: 0 0 0.5em 0.5em; width: 60px; height: 60px; background: url(/images/gravatar.gif) no-repeat left top; float: right; } -#content form.comments { +#content form.discussions { background: #f2f2f2; border-top: 1px solid #ddd; padding: 1em 0.5em; } -#content form.comments fieldset { +#content form.discussions fieldset { border: none; } -#content form.comments legend { +#content form.discussions legend { display: none; } -#content form.comments label { +#content form.discussions label { font-weight: bold; } -#content form.comments textarea { +#content form.discussions textarea { width: 90%; height: 150px; padding: 3px; } diff --git a/test/fixtures/discussions.yml b/test/fixtures/discussions.yml index b49c4eb..c065baa 100644 --- a/test/fixtures/discussions.yml +++ b/test/fixtures/discussions.yml @@ -1,5 +1,9 @@ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html one: id: 1 + page_id: 1 + text: booyah two: id: 2 + page_id: 3 + text: i can has cheeseburger \ No newline at end of file diff --git a/test/functional/discussions_controller_test.rb b/test/functional/discussions_controller_test.rb index 799ad6b..c7dfe25 100644 --- a/test/functional/discussions_controller_test.rb +++ b/test/functional/discussions_controller_test.rb @@ -16,20 +16,14 @@ class DiscussionsControllerTest < Test::Unit::TestCase def test_should_get_index get :index assert_response :success - assert assigns(:discussions) + assert assigns(:pages) end - def test_should_get_new - get :new - assert_response :success - end - def test_should_create_discussion old_count = Discussion.count - post :create, :discussion => { } + post :create, :discussion => { :page_id => 1 } assert_equal old_count+1, Discussion.count - - assert_redirected_to discussion_path(assigns(:discussion)) + assert_response :success end def test_should_show_discussion @@ -37,21 +31,15 @@ class DiscussionsControllerTest < Test::Unit::TestCase assert_response :success end - def test_should_get_edit - get :edit, :id => 1 + def test_should_update_discussion + put :update, :id => 1, :discussion => { :page_id => 1 } assert_response :success end - - def test_should_update_discussion - put :update, :id => 1, :discussion => { } - assert_redirected_to discussion_path(assigns(:discussion)) - end - + def test_should_destroy_discussion old_count = Discussion.count delete :destroy, :id => 1 assert_equal old_count-1, Discussion.count - - assert_redirected_to discussions_path + assert_response :success end end