From a0c96d6a411835ace279f292b7209ecec9c8c03f Mon Sep 17 00:00:00 2001 From: Ethan Vizitei Date: Wed, 4 Jun 2014 15:39:03 -0500 Subject: [PATCH] Add reporting name for learning outcomes fixes CNVS-13242 This adds a special field to learning outcomes to use for friendly reporting in case the outcome's actual name is quite complex or cryptic (like common core standard outcomes). TEST PLAN: - login as an instructor - create or edit an outcome and validate that you can add a "friendly" name and that it persists - use that outcome for an assignment and let a student complete it - navigate to the student mastery report for that student - verify that by hovering over that outcome name on the student mastery report you can see both the real title and the friendly name Change-Id: I89d1a5de590666ddf6cbc82617e4475d1f7a5226 Reviewed-on: https://gerrit.instructure.com/35919 Reviewed-by: Drew Bowman QA-Review: Steven Shepherd Tested-by: Jenkins Product-Review: Drew Bowman --- .../models/grade_summary/Group.coffee | 2 +- .../models/grade_summary/Outcome.coffee | 5 +++ .../outcome_groups_api_controller.rb | 10 ++++- app/controllers/outcomes_api_controller.rb | 13 ++++++- app/models/learning_outcome.rb | 20 +++++----- app/stylesheets/grade_summary.sass | 6 +++ app/stylesheets/learning_outcomes.sass | 3 ++ .../jst/grade_summary/outcome.handlebars | 4 +- .../grade_summary/outcome_detail.handlebars | 4 +- app/views/jst/outcomes/outcomeForm.handlebars | 10 ++++- ...9_add_display_name_to_learning_outcomes.rb | 11 ++++++ lib/api/v1/outcome.rb | 3 +- spec/apis/v1/outcome_groups_api_spec.rb | 5 +++ spec/apis/v1/outcomes_api_spec.rb | 3 ++ spec/lib/api/v1/outcome_spec.rb | 37 +++++++++++++++++++ spec/selenium/helpers/outcome_common.rb | 6 +-- 16 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 db/migrate/20140603193939_add_display_name_to_learning_outcomes.rb create mode 100644 spec/lib/api/v1/outcome_spec.rb diff --git a/app/coffeescripts/models/grade_summary/Group.coffee b/app/coffeescripts/models/grade_summary/Group.coffee index f04f398313e..7d832090051 100644 --- a/app/coffeescripts/models/grade_summary/Group.coffee +++ b/app/coffeescripts/models/grade_summary/Group.coffee @@ -5,7 +5,7 @@ define [ ], (_, {Model, Collection}, natcompare) -> class Group extends Model initialize: -> - @set('outcomes', new Collection([], comparator: natcompare.byGet('title'))) + @set('outcomes', new Collection([], comparator: natcompare.byGet('friendly_name'))) count: -> @get('outcomes').length diff --git a/app/coffeescripts/models/grade_summary/Outcome.coffee b/app/coffeescripts/models/grade_summary/Outcome.coffee index 39983de853b..5cea6f72555 100644 --- a/app/coffeescripts/models/grade_summary/Outcome.coffee +++ b/app/coffeescripts/models/grade_summary/Outcome.coffee @@ -3,6 +3,11 @@ define [ 'Backbone' ], (_, {Model, Collection}) -> class Outcome extends Model + initialize: -> + super + @set 'friendly_name', @get('display_name') || @get('title') + @set 'hover_name', (@get('title') if @get('display_name')) + status: -> if @scoreDefined() score = @get('score') diff --git a/app/controllers/outcome_groups_api_controller.rb b/app/controllers/outcome_groups_api_controller.rb index 5f69bce2333..6e764f2c7bd 100644 --- a/app/controllers/outcome_groups_api_controller.rb +++ b/app/controllers/outcome_groups_api_controller.rb @@ -384,6 +384,10 @@ class OutcomeGroupsApiController < ApplicationController # @argument title [Optional, String] # The title of the new outcome. Required if outcome_id is absent. # + # @argument display_name [Optional, String] + # A friendly name shown in reports for outcomes with cryptic titles, + # such as common core standards names. + # # @argument description [Optional, String] # The description of the new outcome. # @@ -412,6 +416,7 @@ class OutcomeGroupsApiController < ApplicationController # curl 'https:///api/v1/accounts/1/outcome_groups/1/outcomes.json' \ # -X POST \ # -F 'title=Outcome Title' \ + # -F 'display_name=Title for reporting' \ # -F 'description=Outcome description' \ # -F 'vendor_guid=customid9000' \ # -F 'mastery_points=3' \ @@ -429,6 +434,7 @@ class OutcomeGroupsApiController < ApplicationController # -X POST \ # --data-binary '{ # "title": "Outcome Title", + # "display_name": "Title for reporting", # "description": "Outcome description", # "vendor_guid": "customid9000", # "mastery_points": 3, @@ -451,7 +457,7 @@ class OutcomeGroupsApiController < ApplicationController return end else - @outcome = context_create_outcome(params.slice(:title, :description, :ratings, :mastery_points, :vendor_guid)) + @outcome = context_create_outcome(params.slice(:title, :description, :ratings, :mastery_points, :vendor_guid, :display_name)) unless @outcome.valid? render :json => @outcome.errors, :status => :bad_request return @@ -666,7 +672,7 @@ class OutcomeGroupsApiController < ApplicationController def context_create_outcome(data) scope = @context ? @context.created_learning_outcomes : LearningOutcome.global - outcome = scope.build(data.slice(:title, :description, :vendor_guid)) + outcome = scope.build(data.slice(:title, :display_name, :description, :vendor_guid)) if data[:ratings] outcome.rubric_criterion = data.slice(:ratings, :mastery_points) end diff --git a/app/controllers/outcomes_api_controller.rb b/app/controllers/outcomes_api_controller.rb index f46a9d459f2..044bcae2933 100644 --- a/app/controllers/outcomes_api_controller.rb +++ b/app/controllers/outcomes_api_controller.rb @@ -49,6 +49,11 @@ # "example": "Outcome title", # "type": "string" # }, +# "display_name": { +# "description": "Optional friendly name for reporting", +# "example": "My Favorite Outocome", +# "type": "string" +# }, # "description": { # "description": "description of the outcome. omitted in the abbreviated form.", # "example": "Outcome description", @@ -118,6 +123,10 @@ class OutcomesApiController < ApplicationController # @argument title [Optional, String] # The new outcome title. # + # @argument display_name [Optional, String] + # A friendly name shown in reports for outcomes with cryptic titles, + # such as common core standards names. + # # @argument description [Optional, String] # The new outcome description. # @@ -141,6 +150,7 @@ class OutcomesApiController < ApplicationController # curl 'https:///api/v1/outcomes/1.json' \ # -X PUT \ # -F 'title=Outcome Title' \ + # -F 'display_name=Title for reporting' \ # -F 'description=Outcome description' \ # -F 'vendor_guid=customid9001' \ # -F 'mastery_points=3' \ @@ -158,6 +168,7 @@ class OutcomesApiController < ApplicationController # -X PUT \ # --data-binary '{ # "title": "Outcome Title", + # "display_name": "Title for reporting", # "description": "Outcome description", # "vendor_guid": "customid9001", # "mastery_points": 3, @@ -172,7 +183,7 @@ class OutcomesApiController < ApplicationController # def update if authorized_action(@outcome, @current_user, :update) - @outcome.update_attributes(params.slice(:title, :description, :vendor_guid)) + @outcome.update_attributes(params.slice(:title, :display_name, :description, :vendor_guid)) if params[:mastery_points] || params[:ratings] criterion = @outcome.data && @outcome.data[:rubric_criterion] criterion ||= {} diff --git a/app/models/learning_outcome.rb b/app/models/learning_outcome.rb index cea8077d19c..0de71e7d265 100644 --- a/app/models/learning_outcome.rb +++ b/app/models/learning_outcome.rb @@ -18,7 +18,9 @@ class LearningOutcome < ActiveRecord::Base include Workflow - attr_accessible :context, :description, :short_description, :title, :rubric_criterion, :vendor_guid + attr_accessible :context, :description, :short_description, :title, :display_name + attr_accessible :rubric_criterion, :vendor_guid + belongs_to :context, :polymorphic => true validates_inclusion_of :context_type, :allow_nil => true, :in => ['Account', 'Course'] has_many :learning_outcome_results @@ -50,14 +52,14 @@ class LearningOutcome < ActiveRecord::Base given {|user, session| self.context_id.nil? && user } can :read end - + def infer_defaults if self.data && self.data[:rubric_criterion] self.data[:rubric_criterion][:description] = self.short_description end self.context_code = "#{self.context_type.underscore}_#{self.context_id}" rescue nil end - + def align(asset, context, opts={}) tag = self.alignments.find_by_content_id_and_content_type_and_tag_type_and_context_id_and_context_type(asset.id, asset.class.to_s, 'learning_outcome', context.id, context.class.to_s) tag ||= self.alignments.create(:content => asset, :tag_type => 'learning_outcome', :context => context) @@ -73,7 +75,7 @@ class LearningOutcome < ActiveRecord::Base tag.save tag end - + def reorder_alignments(context, order) order_hash = {} order.each_with_index{|o, i| order_hash[o.to_i] = i; order_hash[o] = i } @@ -88,7 +90,7 @@ class LearningOutcome < ActiveRecord::Base self.touch tags end - + def remove_alignment(asset, context, opts={}) tag = self.alignments.find_by_content_id_and_content_type_and_tag_type_and_context_id_and_context_type(asset.id, asset.class.to_s, 'learning_outcome', context.id, context.class.to_s) tag.destroy if tag @@ -123,7 +125,7 @@ class LearningOutcome < ActiveRecord::Base def title=(new_title) self.short_description = new_title end - + workflow do state :active state :retired @@ -135,7 +137,7 @@ class LearningOutcome < ActiveRecord::Base self.context.short_name rescue "" end end - + def rubric_criterion=(hash) self.data ||= {} @@ -178,11 +180,11 @@ class LearningOutcome < ActiveRecord::Base self.workflow_state = 'deleted' save! end - + def tie_to(context) @tied_context = context end - + def artifacts_count_for_tied_context codes = [@tied_context.asset_string] if @tied_context.is_a?(Account) diff --git a/app/stylesheets/grade_summary.sass b/app/stylesheets/grade_summary.sass index 4dcf3705379..b21ac4a7a15 100644 --- a/app/stylesheets/grade_summary.sass +++ b/app/stylesheets/grade_summary.sass @@ -361,6 +361,9 @@ $outcome-border: 1px solid #BCC2CA color: #2a333b p margin: 0 + white-space: nowrap + overflow: hidden + text-overflow: ellipsis .title font-weight: bold @@ -445,3 +448,6 @@ $outcome-border: 1px solid #BCC2CA top: 13px .score font-size: 14px + +.ui-widget.ui-tooltip + max-width: 500px diff --git a/app/stylesheets/learning_outcomes.sass b/app/stylesheets/learning_outcomes.sass index 9df964e2e34..ef2af7b3d03 100644 --- a/app/stylesheets/learning_outcomes.sass +++ b/app/stylesheets/learning_outcomes.sass @@ -33,6 +33,9 @@ height: 500px border-left: 1px solid $borderColor overflow: scroll + .learning_outcome + label.span3 + margin-left: 0px .wrapper padding: 15px width: 600px diff --git a/app/views/jst/grade_summary/outcome.handlebars b/app/views/jst/grade_summary/outcome.handlebars index ed9c3ab7804..48445e508d4 100644 --- a/app/views/jst/grade_summary/outcome.handlebars +++ b/app/views/jst/grade_summary/outcome.handlebars @@ -14,7 +14,9 @@ {{/if}}
-
{{title}}
+
+ {{friendly_name}} +
{{{description}}}
diff --git a/app/views/jst/grade_summary/outcome_detail.handlebars b/app/views/jst/grade_summary/outcome_detail.handlebars index 239a4676759..0e5c19a92bb 100644 --- a/app/views/jst/grade_summary/outcome_detail.handlebars +++ b/app/views/jst/grade_summary/outcome_detail.handlebars @@ -1,5 +1,7 @@
-
{{title}}
+
+ {{friendly_name}} +
{{#if scoreDefined}}{{score}}{{else}}-{{/if}}/{{mastery_points}}
{{view progress}} diff --git a/app/views/jst/outcomes/outcomeForm.handlebars b/app/views/jst/outcomes/outcomeForm.handlebars index 052ebc490e0..01c29ae4c02 100644 --- a/app/views/jst/outcomes/outcomeForm.handlebars +++ b/app/views/jst/outcomes/outcomeForm.handlebars @@ -1,6 +1,12 @@
- - + + + + + + + +