diff --git a/app/controllers/discussion_topics_controller.rb b/app/controllers/discussion_topics_controller.rb index 77541d13efe..6946d7962f0 100644 --- a/app/controllers/discussion_topics_controller.rb +++ b/app/controllers/discussion_topics_controller.rb @@ -48,6 +48,7 @@ class DiscussionTopicsController < ApplicationController # @response_field topic_children An array of topic_ids for the group discussions the user is a part of # @response_field user_name The username of the creator # @response_field url The URL to the discussion topic in canvas + # @response_field discussion_type The type of discussion. Values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions. # @response_field permissions[attach] If true, the calling user can attach files to this discussion's entries. # # @example_response @@ -68,6 +69,7 @@ class DiscussionTopicsController < ApplicationController # "topic_children":[], # "root_topic_id":null, # "podcast_url":"/feeds/topics/1/enrollment_1XAcepje4u228rt4mi7Z1oFbRpn3RAkTzuXIGOPe.rss", + # "discussion_type":"side_comment", # "attachments":[ # { # "content-type":"unknown/unknown", diff --git a/app/models/discussion_topic.rb b/app/models/discussion_topic.rb index 6df78620046..a2ca7d1c5fa 100644 --- a/app/models/discussion_topic.rb +++ b/app/models/discussion_topic.rb @@ -26,7 +26,13 @@ class DiscussionTopic < ActiveRecord::Base attr_accessible :title, :message, :user, :delayed_post_at, :assignment, :plaintext_message, :podcast_enabled, :podcast_has_student_posts, - :require_initial_post, :threaded + :require_initial_post, :threaded, :discussion_type + + module DiscussionTypes + SIDE_COMMENT = 'side_comment' + THREADED = 'threaded' + TYPES = DiscussionTypes.constants.map { |c| DiscussionTypes.const_get(c) } + end attr_readonly :context_id, :context_type, :user_id @@ -48,6 +54,7 @@ class DiscussionTopic < ActiveRecord::Base belongs_to :user validates_presence_of :context_id validates_presence_of :context_type + validates_presence_of :discussion_type, :in => DiscussionTypes::TYPES validates_length_of :message, :maximum => maximum_long_text_length, :allow_nil => true, :allow_blank => true validates_length_of :title, :maximum => maximum_string_length, :allow_nil => true @@ -65,9 +72,22 @@ class DiscussionTopic < ActiveRecord::Base after_create :create_participant after_create :create_materialized_view + def threaded=(v) + self.discussion_type = Canvas::Plugin.value_to_boolean(v) ? DiscussionTypes::THREADED : DiscussionTypes::SIDE_COMMENT + end + + def threaded? + self.discussion_type == DiscussionTypes::THREADED + end + + def discussion_type + read_attribute(:discussion_type) || DiscussionTypes::SIDE_COMMENT + end + def default_values self.context_code = "#{self.context_type.underscore}_#{self.context_id}" self.title ||= t '#discussion_topic.default_title', "No Title" + self.discussion_type = DiscussionTypes::SIDE_COMMENT if !read_attribute(:discussion_type) @content_changed = self.message_changed? || self.title_changed? if self.assignment_id != self.assignment_id_was @old_assignment_id = self.assignment_id_was @@ -106,7 +126,7 @@ class DiscussionTopic < ActiveRecord::Base topic.title = "#{self.title} - #{group.name}" topic.assignment_id = self.assignment_id topic.user_id = self.user_id - topic.threaded = self.threaded + topic.discussion_type = self.discussion_type topic.save if topic.changed? topic end diff --git a/app/views/shared/_topic.html.erb b/app/views/shared/_topic.html.erb index 9e2e545ad0f..3f979648455 100644 --- a/app/views/shared/_topic.html.erb +++ b/app/views/shared/_topic.html.erb @@ -119,7 +119,7 @@ <%= (topic && topic.podcast_enabled) ? "1" : "0" %> <%= (topic && topic.podcast_has_student_posts) ? "1" : "0" %> <%= (topic && topic.require_initial_post) ? "1" : "0" %> - <%= (topic && topic.threaded) ? "1" : "0" %> + <%= topic.try(:threaded?) ? "1" : "0" %> diff --git a/db/migrate/20120328162105_add_discussion_topic_type.rb b/db/migrate/20120328162105_add_discussion_topic_type.rb new file mode 100644 index 00000000000..30cfb59451d --- /dev/null +++ b/db/migrate/20120328162105_add_discussion_topic_type.rb @@ -0,0 +1,13 @@ +class AddDiscussionTopicType < ActiveRecord::Migration + tag :predeploy + + def self.up + remove_column :discussion_topics, :threaded + add_column :discussion_topics, :discussion_type, :string + end + + def self.down + remove_column :discussion_topics, :discussion_type + add_column :discussion_topics, :threaded, :boolean + end +end diff --git a/lib/api/v1/discussion_topics.rb b/lib/api/v1/discussion_topics.rb index 20516a088c5..52f96e15162 100644 --- a/lib/api/v1/discussion_topics.rb +++ b/lib/api/v1/discussion_topics.rb @@ -45,6 +45,7 @@ module Api::V1::DiscussionTopics :methods => [:user_name, :discussion_subentry_count], }, [:attach] ).tap do |json| json.merge! :message => api_user_content(topic.message, context), + :discussion_type => topic.discussion_type, :podcast_url => url, :read_state => topic.read_state(user), :unread_count => topic.unread_count(user), diff --git a/spec/apis/v1/assignments_api_spec.rb b/spec/apis/v1/assignments_api_spec.rb index 960ad61e89b..7ecd8938dcb 100644 --- a/spec/apis/v1/assignments_api_spec.rb +++ b/spec/apis/v1/assignments_api_spec.rb @@ -243,6 +243,7 @@ describe AssignmentsApiController, :type => :integration do 'url' => "http://www.example.com/courses/#{@course.id}/discussion_topics/#{@topic.id}", 'attachments' => [], 'permissions' => { 'attach' => true }, + 'discussion_type' => 'side_comment', } end diff --git a/spec/apis/v1/discussion_topics_api_spec.rb b/spec/apis/v1/discussion_topics_api_spec.rb index d3a223b7955..c853fc39269 100644 --- a/spec/apis/v1/discussion_topics_api_spec.rb +++ b/spec/apis/v1/discussion_topics_api_spec.rb @@ -95,6 +95,7 @@ describe DiscussionTopicsController, :type => :integration do "size"=>attachment.size, }], "topic_children"=>[sub.id], + "discussion_type" => 'side_comment', "permissions" => { "attach" => true }} end @@ -165,6 +166,7 @@ describe DiscussionTopicsController, :type => :integration do "posted_at"=>gtopic.posted_at.as_json, "root_topic_id"=>nil, "topic_children"=>[], + "discussion_type" => 'side_comment', "permissions" => { "attach" => true }} end @@ -826,6 +828,12 @@ describe DiscussionTopicsController, :type => :integration do end context "in the original API" do + it "should respond with information on the threaded discussion" do + json = api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics", + { :controller => "discussion_topics", :action => "index", :format => "json", :course_id => @course.id.to_s }) + json[0]['discussion_type'].should == 'threaded' + end + it "should return nested discussions in a flattened format" do json = api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics/#{@topic.id}/entries", { :controller => "discussion_topics_api", :action => "entries", :format => "json", :course_id => @course.id.to_s, :topic_id => @topic.id.to_s }) diff --git a/spec/factories/discussion_topic_factory.rb b/spec/factories/discussion_topic_factory.rb index e986d4febaf..83295b027b6 100644 --- a/spec/factories/discussion_topic_factory.rb +++ b/spec/factories/discussion_topic_factory.rb @@ -40,7 +40,7 @@ end def topic_with_nested_replies(opts = {}) course_with_teacher(:active_all => true) student_in_course(:course => @course, :active_all => true) - @topic = @course.discussion_topics.create!(:title => "title", :message => "message", :user => @teacher, :threaded => true) + @topic = @course.discussion_topics.create!(:title => "title", :message => "message", :user => @teacher, :discussion_type => 'threaded') @root1 = @topic.reply_from(:user => @student, :html => "root1") @root2 = @topic.reply_from(:user => @student, :html => "root2") @reply1 = @root1.reply_from(:user => @teacher, :html => "reply1") diff --git a/spec/models/discussion_topic_spec.rb b/spec/models/discussion_topic_spec.rb index cbc7fab1b12..e0a1292cf92 100644 --- a/spec/models/discussion_topic_spec.rb +++ b/spec/models/discussion_topic_spec.rb @@ -25,6 +25,17 @@ describe DiscussionTopic do @course.discussion_topics.first.message.should eql("only this should stay") end + it "should default to side_comment type" do + d = DiscussionTopic.new + d.discussion_type.should == 'side_comment' + + d.threaded = '1' + d.discussion_type.should == 'threaded' + + d.threaded = '' + d.discussion_type.should == 'side_comment' + end + it "should update the assignment it is associated with" do course_model a = @course.assignments.create!(:title => "some assignment", :points_possible => 5) @@ -248,10 +259,10 @@ describe DiscussionTopic do it "should copy appropriate attributes from the parent topic to subtopics on updates to the parent" do topic_for_group_assignment subtopics = @topic.refresh_subtopics - subtopics.each {|st| st.threaded.should be_nil } - @topic.threaded = true + subtopics.each {|st| st.discussion_type.should == 'side_comment' } + @topic.discussion_type = 'threaded' @topic.save - subtopics.each {|st| st.reload.threaded.should == true } + subtopics.each {|st| st.reload.discussion_type.should == 'threaded' } end end