Graded discussions with new replies show up in new activity API

fixes ADMIN-105

Test plan
- Create a graded discussion
- As user 1 (probably a teacher), add a comment to the discussion
- As user 2 (probably a student), go to
  /api/v1/planner/items?filter=new_activity
- Ensure the graded discussion shows up in the API
- Ensure it doesn't show up twice in /api/v1/planner/items (or
  anywhere else it shouldn't)

Change-Id: I21a88a4e5181e2a43ce5d03cf92230d3107d5093
Reviewed-on: https://gerrit.instructure.com/132096
Tested-by: Jenkins
Reviewed-by: Dan Minkevitch <dan@instructure.com>
QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com>
Product-Review: Pert Eilers <peilers@instructure.com>
This commit is contained in:
Mysti Sadler 2017-11-07 12:47:05 -07:00
parent 2c7c43b0ea
commit 4e1a29de82
7 changed files with 53 additions and 6 deletions

View File

@ -325,7 +325,7 @@ class PlannerOverridesController < ApplicationController
def unread_discussion_topic_collection def unread_discussion_topic_collection
item_collection('unread_discussion_topics', item_collection('unread_discussion_topics',
@current_user.discussion_topics_needing_viewing(scope_only: true, include_ignored: true, @current_user.discussion_topics_needing_viewing(scope_only: true, include_ignored: true,
due_before: end_date, due_after: start_date). due_before: end_date, due_after: start_date, new_activity: true).
unread_for(@current_user), unread_for(@current_user),
DiscussionTopic, [:todo_date, :posted_at, :delayed_post_at, :last_reply_at, :created_at], :id) DiscussionTopic, [:todo_date, :posted_at, :delayed_post_at, :last_reply_at, :created_at], :id)
end end

View File

@ -1650,7 +1650,7 @@ class User < ActiveRecord::Base
if opts[:scope_only] if opts[:scope_only]
Shard.partition_by_shard(course_ids) do |shard_course_ids| Shard.partition_by_shard(course_ids) do |shard_course_ids|
next unless Shard.current == original_shard # only provideo scope on current shard next unless Shard.current == original_shard # only provide scope on current shard
return yield(*arguments_for_needing_viewing(object_type, shard_course_ids, opts)) return yield(*arguments_for_needing_viewing(object_type, shard_course_ids, opts))
end end
return object_type.constantize.none return object_type.constantize.none
@ -1673,8 +1673,13 @@ class User < ActiveRecord::Base
def arguments_for_needing_viewing(object_type, shard_course_ids, opts) def arguments_for_needing_viewing(object_type, shard_course_ids, opts)
scope = object_type.constantize.for_courses_and_groups(shard_course_ids, cached_current_group_memberships.map(&:group_id)) scope = object_type.constantize.for_courses_and_groups(shard_course_ids, cached_current_group_memberships.map(&:group_id))
scope = scope.not_ignored_by(self, 'viewing') unless opts[:include_ignored] scope = scope.not_ignored_by(self, 'viewing') unless opts[:include_ignored]
scope = scope.todo_date_between(opts[:due_after], opts[:due_before]) scope_todo = scope.todo_date_between(opts[:due_after], opts[:due_before])
[scope, opts.merge(:shard_course_ids => shard_course_ids)] if object_type == 'DiscussionTopic' && opts[:new_activity]
scope_todo = scope_todo.or(scope.where(assignment_id:
Assignment.active.where(context_id: shard_course_ids, context_type: 'Course', submission_types: 'discussion_topic').
due_between_with_overrides(opts[:due_after], opts[:due_before]).pluck(:id)))
end
[scope_todo, opts.merge(:shard_course_ids => shard_course_ids)]
end end
def discussion_topics_needing_viewing(opts={}) def discussion_topics_needing_viewing(opts={})

View File

@ -35,6 +35,7 @@ module Api::V1::PlannerItem
}.freeze }.freeze
def planner_item_json(item, user, session, opts = {}) def planner_item_json(item, user, session, opts = {})
item = item.assignment if item.respond_to?(:assignment) && item.assignment
context_data(item).merge({ context_data(item).merge({
:plannable_id => item.id, :plannable_id => item.id,
:plannable_date => item.planner_date, :plannable_date => item.planner_date,

View File

@ -507,6 +507,30 @@ describe PlannerOverridesController do
get :items_index, params: {filter: "new_activity"} get :items_index, params: {filter: "new_activity"}
expect(json_parse(response.body).length).to eq 1 expect(json_parse(response.body).length).to eq 1
end end
it "should return graded discussions with unread replies" do
@topic.change_read_state('read', @student)
assign = assignment_model(course: @course, due_at: Time.zone.now)
topic = @course.discussion_topics.create!(course: @course, assignment: assign)
topic.change_read_state('read', @student)
get :items_index, params: {filter: "new_activity"}
expect(json_parse(response.body)).to be_empty
entry = topic.discussion_entries.create!(:message => "Hello!", :user => @student)
reply = entry.reply_from(:user => @teacher, :text => "ohai!")
topic.reload
get :items_index, params: {filter: "new_activity"}
response_json = json_parse(response.body)
expect(response_json.length).to eq 1
expect(response_json.first["plannable_id"]).to eq assign.id
expect(response_json.first["plannable"]["id"]).to eq topic.id
reply.change_read_state('read', @student)
get :items_index, params: {filter: "new_activity"}
expect(json_parse(response.body)).to be_empty
end
end end
end end
end end

View File

@ -80,6 +80,7 @@ module Factories
@assignment.saved_by = :discussion_topic @assignment.saved_by = :discussion_topic
@topic.assignment = @assignment @topic.assignment = @assignment
@topic.save! @topic.save!
@assignment.reload
@topic @topic
end end

View File

@ -77,6 +77,13 @@ describe Api::V1::PlannerItem do
expect(annc_hash[:plannable_date]).to eq annc_post_date expect(annc_hash[:plannable_date]).to eq annc_post_date
end end
it 'should show the assignment for the plannable_id if one exists' do
asg = assignment_model course: @couse, submission_types: 'online_text_entry'
dt = @course.discussion_topics.create!(assignment: asg, title: 'Assignment DT')
dt_hash = api.planner_item_json(dt, @student, session)
expect(dt_hash[:plannable_id]).to eq asg.id
end
context 'with an existing planner override' do context 'with an existing planner override' do
it 'should return the planner visibility state' do it 'should return the planner visibility state' do
teacher_hash = api.planner_item_json(@assignment, @teacher, session) teacher_hash = api.planner_item_json(@assignment, @teacher, session)

View File

@ -2342,8 +2342,8 @@ describe User do
expect(@student.discussion_topics_needing_viewing(opts)).to eq [] expect(@student.discussion_topics_needing_viewing(opts)).to eq []
end end
it 'should not show discussions that are graded' do it 'should not show discussions that are graded unless new_activity is true' do
a = @course.assignments.create!(title: "some assignment", points_possible: 5) a = @course.assignments.create!(title: "some assignment", points_possible: 5, due_at: 1.day.from_now)
t = @course.discussion_topics.build(assignment: a, title: "some topic", message: "a little bit of content") t = @course.discussion_topics.build(assignment: a, title: "some topic", message: "a little bit of content")
t.save t.save
expect(t.assignment_id).to eql(a.id) expect(t.assignment_id).to eql(a.id)
@ -2351,6 +2351,15 @@ describe User do
expect(@student.discussion_topics_needing_viewing(opts)).not_to include t expect(@student.discussion_topics_needing_viewing(opts)).not_to include t
end end
it 'should show graded discussion if new activity is true' do
a = @course.assignments.create!(title: "some assignment", points_possible: 5, due_at: 1.day.from_now)
t = @course.discussion_topics.build(assignment: a, title: "some topic", message: "a little bit of content")
t.save
expect(t.assignment_id).to eql(a.id)
expect(t.assignment).to eql(a)
expect(@student.discussion_topics_needing_viewing(opts.merge({new_activity: true}))).to include t
end
context "locked discussion topics" do context "locked discussion topics" do
it 'should show for ungraded discussion topics with unlock dates and todo dates within the opts date range' do it 'should show for ungraded discussion topics with unlock dates and todo dates within the opts date range' do
@topic.unlock_at = 1.day.from_now @topic.unlock_at = 1.day.from_now