Standardize where planner overrides live

closes ADMIN-143

Test plan
- Have a graded quiz, discussion and wiki page
- Try to create planner overrides for the
  assignments for all of them
- Ensure the planner override gets created for
  the quiz/discussion/wiki page instead
- Have a group discussion
- Try to create a planner override for one of
  the child topics
- Ensure the planner override gets created for
  the parent topic
- Have an announcement and create a planner
  override for it
- Make an api call for the override and ensure
  it shows up as "announcement" in the type
  instead of discussion_topic

Change-Id: I7940f27508453cdc03366eda10d59e5ca1fbf110
Reviewed-on: https://gerrit.instructure.com/156904
Tested-by: Jenkins
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
QA-Review: Anju Reddy <areddy@instructure.com>
Product-Review: Mysti Sadler <mysti@instructure.com>
This commit is contained in:
Mysti Sadler 2018-07-09 17:30:04 -06:00
parent afc379a6c1
commit 6f7062a96e
7 changed files with 67 additions and 25 deletions

View File

@ -156,8 +156,7 @@ class PlannerOverridesController < ApplicationController
def create
plannable_type = PLANNABLE_TYPES[params[:plannable_type]]
plannable = plannable_type.constantize.find(params[:plannable_id])
planner_override = PlannerOverride.new(plannable_type: plannable_type,
plannable_id: params[:plannable_id], marked_complete: value_to_boolean(params[:marked_complete]),
planner_override = PlannerOverride.new(plannable: plannable, marked_complete: value_to_boolean(params[:marked_complete]),
user: @current_user, dismissed: value_to_boolean(params[:dismissed]))
sync_module_requirement_done(plannable, @current_user, value_to_boolean(params[:marked_complete]))

View File

@ -20,7 +20,7 @@
module PlannerHelper
PLANNABLE_TYPES = {
'discussion_topic' => 'DiscussionTopic',
'announcement' => 'DiscussionTopic',
'announcement' => 'Announcement',
'quiz' => 'Quizzes::Quiz',
'assignment' => 'Assignment',
'wiki_page' => 'WikiPage',

View File

@ -17,18 +17,23 @@
#
class PlannerOverride < ActiveRecord::Base
CONTENT_TYPES = %w(Announcement Assignment DiscussionTopic Quizzes::Quiz WikiPage PlannerNote).freeze
include Workflow
include PlannerHelper
CONTENT_TYPES = PLANNABLE_TYPES.values
before_validation :link_to_parent_topic, :link_to_submittable
belongs_to :plannable, polymorphic:
[:announcement, :assignment, :discussion_topic, :planner_note, :wiki_page, :calendar_event, quiz: 'Quizzes::Quiz']
belongs_to :user
validates_presence_of :plannable_id, :workflow_state, :user_id
validates_uniqueness_of :plannable_id, scope: [:user_id, :plannable_type]
validates :plannable_id, :plannable_type, :workflow_state, :user_id, presence: true
validates :plannable_id, uniqueness: {scope: [:user_id, :plannable_type]}
scope :active, -> { where workflow_state: 'active' }
scope :deleted, -> { where workflow_state: 'deleted' }
scope :not_deleted, -> { where.not deleted }
scope :for_user, -> (user) { where user: user }
workflow do
state :active do
@ -40,17 +45,34 @@ class PlannerOverride < ActiveRecord::Base
state :deleted
end
alias_method :published?, :active?
alias published? active?
def link_to_parent_topic
return unless self.plannable_type == 'DiscussionTopic'
plannable = DiscussionTopic.find(self.plannable_id)
self.plannable_id = plannable.root_topic_id if plannable.root_topic_id
end
def link_to_submittable
return unless self.plannable_type == 'Assignment'
plannable = Assignment.find_by(id: self.plannable_id)
if plannable&.quiz?
self.plannable_type = PLANNABLE_TYPES['quiz']
self.plannable_id = plannable.quiz.id
elsif plannable&.discussion_topic?
self.plannable_type = PLANNABLE_TYPES['discussion_topic']
self.plannable_id = plannable.discussion_topic.id
elsif plannable&.wiki_page?
self.plannable_type = PLANNABLE_TYPES['wiki_page']
self.plannable_id = plannable.wiki_page.id
end
end
def self.update_for(obj)
overrides = PlannerOverride.where(plannable_id: obj.id, plannable_type: obj.class.to_s)
overrides.update_all(workflow_state: plannable_workflow_state(obj)) if overrides.exists?
end
def self.for_user(user)
overrides = PlannerOverride.where(user_id: user)
end
def self.plannable_workflow_state(plannable)
if plannable.respond_to?(:published?)
if plannable.respond_to?(:deleted?) && plannable.deleted?

View File

@ -31,17 +31,16 @@ module Api::V1::PlannerItem
def planner_item_json(item, user, session, opts = {})
context_data(item, use_effective_code: true).merge({
:plannable_id => item.id,
:planner_override => planner_override_json(item.planner_override_for(user), user, session),
:planner_override => planner_override_json(item.planner_override_for(user), user, session, item.class_name),
:plannable_type => PLANNABLE_TYPES.key(item.class_name),
:new_activity => new_activity(item, user, opts)
}).merge(submission_statuses_for(user, item, opts)).tap do |hash|
assignment_opts = {exclude_response_fields: ['rubric']}
if item.is_a?(::CalendarEvent)
hash[:plannable_date] = item.start_at || item.created_at
hash[:plannable_type] = 'calendar_event'
hash[:plannable] = event_json(item, user, session)
elsif item.is_a?(::PlannerNote)
hash[:plannable_date] = item.todo_date || item.created_at
hash[:plannable_type] = 'planner_note'
hash[:plannable] = planner_note_json(item, user, session)
# TODO: We don't currently have an html_url for individual planner items.
# hash[:html_url] = ???
@ -49,32 +48,30 @@ module Api::V1::PlannerItem
hash[:plannable_date] = item[:user_due_date] || item.due_at
quiz = item.is_a?(Quizzes::Quiz) ? item : item.quiz
hash[:plannable_id] = quiz.id
hash[:plannable_type] = 'quiz'
hash[:plannable_type] = PLANNABLE_TYPES.key(quiz.class_name)
hash[:plannable] = quiz_json(quiz, quiz.context, user, session)
hash[:html_url] = named_context_url(quiz.context, :context_quiz_url, quiz.id)
hash[:planner_override] ||= planner_override_json(quiz.planner_override_for(user), user, session)
elsif item.is_a?(WikiPage) || (item.respond_to?(:wiki_page?) && item.wiki_page?)
item = item.wiki_page if item.respond_to?(:wiki_page?) && item.wiki_page?
hash[:plannable_date] = item.todo_date || item.created_at
hash[:plannable_type] = 'wiki_page'
hash[:plannable_type] = PLANNABLE_TYPES.key(item.class_name)
hash[:plannable] = wiki_page_json(item, user, session, false, assignment_opts: assignment_opts)
hash[:html_url] = named_context_url(item.context, :context_wiki_page_url, item.url)
hash[:planner_override] ||= planner_override_json(item.planner_override_for(user), user, session)
elsif item.is_a?(Announcement)
hash[:plannable_date] = item.posted_at || item.created_at
hash[:plannable_type] = 'announcement'
hash[:plannable] = discussion_topic_api_json(item, item.context, user, session, use_preload: true)
hash[:html_url] = named_context_url(item.context, :context_discussion_topic_url, item.id)
elsif item.is_a?(DiscussionTopic) || (item.respond_to?(:discussion_topic?) && item.discussion_topic?)
topic = item.is_a?(DiscussionTopic) ? item : item.discussion_topic
hash[:plannable_id] = topic.id
hash[:plannable_date] = item[:user_due_date] || topic.todo_date || topic.posted_at || topic.created_at
hash[:plannable_type] = 'discussion_topic'
hash[:plannable_type] = PLANNABLE_TYPES.key(topic.class_name)
hash[:plannable] = discussion_topic_api_json(topic, topic.context, user, session, assignment_opts: assignment_opts, use_preload: true)
hash[:html_url] = discussion_topic_html_url(topic, user, hash[:submissions])
hash[:planner_override] ||= planner_override_json(topic.planner_override_for(user), user, session)
hash[:planner_override] ||= planner_override_json(topic.planner_override_for(user), user, session, topic.class_name)
else
hash[:plannable_type] = 'assignment'
hash[:plannable_date] = item[:user_due_date] || item.due_at
hash[:plannable] = assignment_json(item, user, session, {include_discussion_topic: true}.merge(assignment_opts))
hash[:html_url] = assignment_html_url(item, user, hash[:submissions])

View File

@ -20,10 +20,11 @@ module Api::V1::PlannerOverride
include Api::V1::Json
include PlannerHelper
def planner_override_json(override, user, session)
def planner_override_json(override, user, session, type=nil)
return if override.blank?
json = api_json(override, user, session)
json['plannable_type'] = PLANNABLE_TYPES.key(json['plannable_type'])
type = override.plannable.type if override.plannable_type == 'DiscussionTopic' && type.nil?
json['plannable_type'] = PLANNABLE_TYPES.key(type || json['plannable_type'])
json
end
end

View File

@ -114,11 +114,11 @@ describe PlannerOverridesController do
post :create, params: {plannable_type: "assignment", plannable_id: @assignment2.id, marked_complete: true}
end
it "should save announcement overrides with a plannable_type of discussion_topic" do
it "should save announcement overrides with a plannable_type of announcement" do
announcement_model(context: @course)
post :create, params: {plannable_type: 'announcement', plannable_id: @a.id, user_id: @student.id, marked_complete: true}
json = json_parse(response.body)
expect(json["plannable_type"]).to eq 'discussion_topic'
expect(json["plannable_type"]).to eq 'announcement'
end
end

View File

@ -33,6 +33,29 @@ describe PlannerOverride do
marked_complete: false)
end
it 'should link the planner override to the parent topic for a group discussion if given a child topic id' do
group_assignment_discussion(course: @course)
override1 = PlannerOverride.create!(user: @student, plannable: @topic)
expect(override1.plannable_type).to eq 'DiscussionTopic'
expect(override1.plannable_id).to eq @topic.root_topic_id
end
it "should link the planner override to its submittable object instead of assignment if it has one" do
assignment_model(course: @course, submission_types: 'discussion_topic')
override1 = PlannerOverride.create!(user: @student, plannable: @assignment)
expect(override1.plannable_type).to eq 'DiscussionTopic'
expect(override1.plannable_id).to eq @assignment.discussion_topic.id
wiki_page_assignment_model(course: @course)
override2 = PlannerOverride.create!(user: @student, plannable: @page.assignment)
expect(override2.plannable_type).to eq 'WikiPage'
expect(override2.plannable_id).to eq @page.id
assignment_model(course: @course, submission_types: 'online_quiz', quiz: quiz_model(course: @course))
override3 = PlannerOverride.create!(user: @student, plannable: @assignment)
expect(override3.plannable_type).to eq 'Quizzes::Quiz'
expect(override3.plannable_id).to eq @assignment.quiz.id
end
describe "::plannable_workflow_state" do
context "respond_to?(:published?)" do