Redesign the To-Do, Coming Up, and Recent Feedback lists
Fixes CNVS-25877 Test plan: - Create a user with: - an assignment that needs to be submitted - an assignment that needs to be graded - an assignment whose grades the user needs to moderate - an assignment that they need to peer review - a calendar event that they can see - Go to the user's home page - Ensure all of the assignments show up in the to-do list - Ensure they show up in Coming Up as well - Ensure that the calendar event shows up under Coming Up - Go to the courses where you created the assignments - Ensure that each assignment shows up on its respective course to-do list - Submit an assignment - As a teacher, ensure that the assignment shows up as needing grading, and that the number in the badge to the left is 1 - Ensure that screenreaders read the badge as "1 submission needs grading" - Make another submission as a different user - Clear the cache by running `Rails.cache.clear` at a Rails console - As the teacher, ensure that the badge is now 2 - Ensure that screenreaders read the badge as "2 submissions need grading" - Repeat 8 more times as different users, so that there are now 10 submissions - Clear the cache again - Ensure that the badge now says "9+" - Ensure that screenreaders read the badge as "More than 9 submissions need grading" - As the user who submitted the assignment, ensure that the grade shows up on the To-Do list, Coming Up, and Recent Feedback - As a teacher, leave a submission comment - As the user who submitted the assignment, ensure that the comment shows up under Recent Feedback - Create a public course - You can make a course public by going to its settings page and checking "Make this course publicly visible" - Log out - Visit /courses/<id>, where <id> is the id of the course - Ensure that the course shows as expected, and that nothing shows up on the to-do list - Automated tests should cover everything else Change-Id: I18673995db94d896bf2c39515258e61065b48319 Reviewed-on: https://gerrit.instructure.com/69474 Reviewed-by: Andrew Butterfield <abutterfield@instructure.com> QA-Review: Heath Hales <hhales@instructure.com> Tested-by: Jenkins Product-Review: Allison Weiss <allison@instructure.com>
This commit is contained in:
parent
db87c8a555
commit
7799495aa3
|
@ -534,12 +534,12 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def cached_submissions(user, upcoming_events)
|
||||
Rails.cache.fetch(['cached_user_submissions', user].cache_key,
|
||||
Rails.cache.fetch(['cached_user_submissions2', user].cache_key,
|
||||
:expires_in => 3.minutes) do
|
||||
assignments = upcoming_events.select{ |e| e.is_a?(Assignment) }
|
||||
Shard.partition_by_shard(assignments) do |shard_assignments|
|
||||
Submission.
|
||||
select([:id, :assignment_id, :score, :workflow_state, :updated_at]).
|
||||
select([:id, :assignment_id, :score, :grade, :workflow_state, :updated_at]).
|
||||
where(:assignment_id => shard_assignments, :user_id => user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -43,12 +43,16 @@ module AssignmentsHelper
|
|||
link_to submission_author_name_for(assessment), context_url(context, :context_assignment_submission_url, assignment.id, assessment.asset.user_id), link_options
|
||||
end
|
||||
|
||||
def due_at(assignment, user, format='datetime')
|
||||
def due_at(assignment, user)
|
||||
if assignment.multiple_due_dates_apply_to?(user)
|
||||
multiple_due_dates(assignment)
|
||||
else
|
||||
assignment = assignment.overridden_for(user)
|
||||
send("#{format}_string", assignment.due_at, :short)
|
||||
if assignment.due_at
|
||||
datetime_string(assignment.due_at)
|
||||
else
|
||||
I18n.t('No Due Date')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
class ToDoListPresenter
|
||||
ASSIGNMENT_LIMIT = 100
|
||||
VISIBLE_LIMIT = 5
|
||||
|
||||
attr_reader :needs_grading, :needs_moderation, :needs_submitting, :needs_reviewing
|
||||
|
||||
def initialize(view, user, contexts)
|
||||
@view = view
|
||||
@user = user
|
||||
@contexts = contexts
|
||||
|
||||
if user
|
||||
@needs_grading = assignments_needing(:grading)
|
||||
@needs_moderation = assignments_needing(:moderation)
|
||||
@needs_submitting = assignments_needing(:submitting)
|
||||
assessment_requests = user.submissions_needing_peer_review(contexts: contexts, limit: ASSIGNMENT_LIMIT)
|
||||
@needs_reviewing = assessment_requests.map do |ar|
|
||||
AssessmentRequestPresenter.new(view, ar, user) if ar.asset.assignment.published?
|
||||
end.compact
|
||||
else
|
||||
@needs_grading = []
|
||||
@needs_moderation = []
|
||||
@needs_submitting = []
|
||||
@needs_reviewing = []
|
||||
end
|
||||
end
|
||||
|
||||
def assignments_needing(type)
|
||||
if @user
|
||||
@user.send("assignments_needing_#{type}", contexts: @contexts, limit: ASSIGNMENT_LIMIT).map do |assignment|
|
||||
AssignmentPresenter.new(@view, assignment, @user, type)
|
||||
end
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def any_assignments?
|
||||
@user && (
|
||||
@needs_grading.present? ||
|
||||
@needs_moderation.present? ||
|
||||
@needs_submitting.present? ||
|
||||
@needs_reviewing.present?
|
||||
)
|
||||
end
|
||||
|
||||
# False when there's only one context (no point in showing its name beneath each assignment), true otherwise.
|
||||
def show_context?
|
||||
@contexts.nil? || @contexts.length > 1
|
||||
end
|
||||
|
||||
def visible_limit
|
||||
VISIBLE_LIMIT
|
||||
end
|
||||
|
||||
def hidden_count_for(items)
|
||||
if items.length > visible_limit
|
||||
items.length - visible_limit
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def hidden_count
|
||||
@hidden_count ||= [needs_grading, needs_moderation, needs_submitting, needs_reviewing].sum do |items|
|
||||
hidden_count_for(items)
|
||||
end
|
||||
end
|
||||
|
||||
class AssignmentPresenter
|
||||
attr_reader :assignment
|
||||
protected :assignment
|
||||
delegate :title, :submission_action_string, :points_possible, :due_at, :peer_reviews_due_at, to: :assignment
|
||||
|
||||
def initialize(view, assignment, user, type)
|
||||
@view = view
|
||||
@assignment = assignment
|
||||
@user = user
|
||||
@type = type
|
||||
end
|
||||
|
||||
def needs_moderation_icon_data
|
||||
@view.icon_data(context: assignment.context, current_user: @user, recent_event: assignment)
|
||||
end
|
||||
|
||||
def needs_submitting_icon_data
|
||||
@view.icon_data(context: assignment.context, current_user: @user, recent_event: assignment, student_only: true)
|
||||
end
|
||||
|
||||
def context_name
|
||||
@assignment.context.nickname_for(@user)
|
||||
end
|
||||
|
||||
def needs_grading_count
|
||||
@needs_grading_count ||= Assignments::NeedsGradingCountQuery.new(@assignment, @user).count
|
||||
end
|
||||
|
||||
def needs_grading_badge
|
||||
if needs_grading_count > 9
|
||||
I18n.t('%{more_than}+', more_than: 9)
|
||||
else
|
||||
needs_grading_count
|
||||
end
|
||||
end
|
||||
|
||||
def needs_grading_label
|
||||
if needs_grading_count > 9
|
||||
I18n.t('More than 9 submissions need grading')
|
||||
else
|
||||
I18n.t({one: '1 submission needs grading', other: '%{count} submissions need grading'}, count: assignment.needs_grading_count)
|
||||
end
|
||||
end
|
||||
|
||||
def gradebook_path
|
||||
@view.speed_grader_course_gradebook_path(assignment.context_id, assignment_id: assignment.id)
|
||||
end
|
||||
|
||||
def moderate_path
|
||||
@view.course_assignment_moderate_path(assignment.context_id, assignment)
|
||||
end
|
||||
|
||||
def assignment_path
|
||||
@view.course_assignment_path(assignment.context_id, assignment.id)
|
||||
end
|
||||
|
||||
def ignore_url
|
||||
@view.todo_ignore_api_url(@type, @assignment)
|
||||
end
|
||||
|
||||
def ignore_title
|
||||
case @type
|
||||
when :grading
|
||||
I18n.t('Ignore until new submission')
|
||||
when :moderation
|
||||
I18n.t('Ignore until new mark')
|
||||
when :submitting
|
||||
I18n.t('Ignore this assignment')
|
||||
end
|
||||
end
|
||||
|
||||
def ignore_flash_message
|
||||
case @type
|
||||
when :grading
|
||||
I18n.t('This item will reappear when a new submission is made.')
|
||||
when :moderation
|
||||
I18n.t('This item will reappear when there are new grades to moderate.')
|
||||
end
|
||||
end
|
||||
|
||||
def formatted_due_date
|
||||
@view.due_at(assignment, @user)
|
||||
end
|
||||
|
||||
def formatted_peer_review_due_date
|
||||
if assignment.peer_reviews_due_at
|
||||
@view.datetime_string(assignment.peer_reviews_due_at)
|
||||
else
|
||||
I18n.t('No Due Date')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class AssessmentRequestPresenter
|
||||
delegate :context_name, to: :assignment_presenter
|
||||
attr_reader :assignment
|
||||
|
||||
def initialize(view, assessment_request, user)
|
||||
@view = view
|
||||
@assessment_request = assessment_request
|
||||
@user = user
|
||||
@assignment = assessment_request.asset.assignment
|
||||
end
|
||||
|
||||
def published?
|
||||
@assessment_request.asset.assignment.published?
|
||||
end
|
||||
|
||||
def assignment_presenter
|
||||
AssignmentPresenter.new(@view, @assignment, @user, :reviewing)
|
||||
end
|
||||
|
||||
def submission_path
|
||||
@view.course_assignment_submission_path(@assignment.context_id, @assignment.id, @assessment_request.user_id)
|
||||
end
|
||||
|
||||
def ignore_url
|
||||
@view.todo_ignore_api_url('reviewing', @assessment_request)
|
||||
end
|
||||
|
||||
def ignore_title
|
||||
I18n.t('Ignore this assignment')
|
||||
end
|
||||
|
||||
def ignore_flash_message
|
||||
end
|
||||
|
||||
def submission_author_name
|
||||
@view.submission_author_name_for(@assessment_request, "#{I18n.t('user')}: ")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -60,7 +60,7 @@
|
|||
margin-bottom: $right_side_margin;
|
||||
}
|
||||
|
||||
.right-side-list {
|
||||
#right-side .right-side-list {
|
||||
@include reset-list;
|
||||
@if $use_new_styles { margin: 0 0 $ic-sp; }
|
||||
@else { margin: 10px 0; }
|
||||
|
@ -78,7 +78,7 @@
|
|||
b, &.more_link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
em {
|
||||
em, p {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
@ -107,16 +107,18 @@
|
|||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
b, em {
|
||||
b, em, p {
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
em, .more_link {
|
||||
font-style: italic;
|
||||
p, .more_link {
|
||||
@include fontSize(12px);
|
||||
line-height: 13px;
|
||||
}
|
||||
em {
|
||||
em, .more_link {
|
||||
font-style: italic;
|
||||
}
|
||||
em, p {
|
||||
@if $use_high_contrast {
|
||||
color: #555;
|
||||
}
|
||||
|
@ -125,6 +127,9 @@
|
|||
}
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.more_link {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
@ -139,6 +144,7 @@
|
|||
.recent_feedback_comment {
|
||||
color: $gray-light;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
}
|
||||
.tooltip {
|
||||
.tooltip_wrap {
|
||||
|
@ -164,6 +170,16 @@
|
|||
height: 1px;
|
||||
}
|
||||
}
|
||||
&.to-do-list, &.events {
|
||||
i {
|
||||
width: 25px;
|
||||
}
|
||||
.todo-badge-wrapper {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
min-width: 25px;
|
||||
}
|
||||
}
|
||||
&.to-do-list {
|
||||
li {
|
||||
position: relative;
|
||||
|
|
|
@ -313,6 +313,11 @@
|
|||
@if $use_new_styles { color: $ic-color-success; }
|
||||
@else { color: #33802a; }
|
||||
}
|
||||
.todo-badge {
|
||||
@include ic-badge-maker(18px);
|
||||
vertical-align: top;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
div.event-details, div.todo-details {
|
||||
display: inline-block;
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
<%
|
||||
# This is rendered both on the dashboard and on the course homepage. On the
|
||||
# dashboard, contexts is nil, and so the cache is only based on the user, which
|
||||
# does not get touched when an assignment needs_grading count changes. So for
|
||||
# the dashboard, we expire after 3 minutes. On the course page, contexts is the
|
||||
# course, which does get touched, and so the cache expiration works.
|
||||
#
|
||||
# BTW if you add a new thing here, it probably needs adding to the /users/self/todo API
|
||||
cache_opts = (contexts.present? ? {} : { :expires_in => 3.minutes })
|
||||
cache(safe_cache_key([@current_user, contexts, 'a_need_grading']), cache_opts) do
|
||||
show_context = !contexts || contexts.length > 1
|
||||
visible_limit = 5
|
||||
needs_grading = @current_user ? @current_user.assignments_needing_grading(:contexts => contexts, :limit => 100) : []
|
||||
needs_moderation = @current_user ? @current_user.assignments_needing_moderation(:contexts => contexts, :limit => 100) : []
|
||||
needs_submitting = @current_user ? @current_user.assignments_needing_submitting(:contexts => contexts, :limit => 100) : []
|
||||
needs_reviewing = @current_user ? @current_user.submissions_needing_peer_review(:contexts => contexts, :limit => 100) : []
|
||||
hidden_todos = 0
|
||||
%>
|
||||
|
||||
<% if @current_user && needs_grading.present? || needs_moderation.present? || needs_submitting.present? || needs_reviewing.present? %>
|
||||
<h2><%= t('headings.to_do', %{To Do}) %></h2>
|
||||
<ul class="right-side-list to-do-list">
|
||||
<% needs_grading.each_with_index do |assignment, i| %>
|
||||
<% icon_explanation, icon_aria_label, icon_class = icon_data(context: assignment.context,
|
||||
current_user: @current_user,
|
||||
recent_event: assignment)
|
||||
%>
|
||||
<li class="todo" style="<%= hidden if i >= visible_limit %>">
|
||||
<a
|
||||
class="item tooltip"
|
||||
href="<%= speed_grader_course_gradebook_path( assignment.context_id, :assignment_id => assignment.id) %>"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs grading"
|
||||
>
|
||||
<% if assignment.due_at || assignment.points_possible || show_context %>
|
||||
<span class="tooltip_wrap">
|
||||
<span class='tooltip-carat'></span>
|
||||
<span class="tooltip_text">
|
||||
<span style="display: block;"><%= translated_due_date(assignment) %></span>
|
||||
<% if assignment.points_possible %>
|
||||
<span style="display: block; font-size: 0.8em;"><%= t 'points_possible', 'out of %{points_possible}', :points_possible => assignment.points_possible %></span>
|
||||
<% end %>
|
||||
<% if show_context %>
|
||||
<span style="display: block; font-size: 0.8em;"><%= assignment.context.short_name %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
</span>
|
||||
<% end %>
|
||||
<i class="<%= icon_class %>" aria-label="<%= icon_aria_label %>"></i>
|
||||
<div class="todo-details">
|
||||
<b><%= t 'headings.grade', 'Grade %{assignment}', :assignment => assignment.title %></b>
|
||||
<em>
|
||||
<%= t 'need_grading_count', { one: '1 needs grading', other: '%{count} need grading' }, count: Assignments::NeedsGradingCountQuery.new(assignment, @current_user).count %>
|
||||
</em>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'grading', :item => assignment } %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% needs_moderation.each_with_index do |assignment, i| %>
|
||||
<% icon_explanation, icon_aria_label, icon_class = icon_data(context: assignment.context,
|
||||
current_user: @current_user,
|
||||
recent_event: assignment)
|
||||
%>
|
||||
<li class="todo" style="<%= hidden if i >= visible_limit %>">
|
||||
<a
|
||||
class="item tooltip"
|
||||
href="<%= course_assignment_moderate_path(assignment.context_id, assignment) %>"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs moderation"
|
||||
>
|
||||
<% if assignment.due_at || assignment.points_possible || show_context %>
|
||||
<span class="tooltip_wrap">
|
||||
<span class='tooltip-carat'></span>
|
||||
<span class="tooltip_text">
|
||||
<span style="display: block;"><%= translated_due_date(assignment) %></span>
|
||||
<% if assignment.points_possible %>
|
||||
<span style="display: block; font-size: 0.8em;"><%= t 'points_possible', 'out of %{points_possible}', :points_possible => assignment.points_possible %></span>
|
||||
<% end %>
|
||||
<% if show_context %>
|
||||
<span style="display: block; font-size: 0.8em;"><%= assignment.context.short_name %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
</span>
|
||||
<% end %>
|
||||
<i class="<%= icon_class %>" aria-label="<%= icon_aria_label %>"></i>
|
||||
<div class="todo-details">
|
||||
<b><%= t 'headings.moderate', 'Moderate %{assignment}', :assignment => assignment.title %></b>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'moderation', :item => assignment } %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% needs_submitting.each_with_index do |assignment, i| %>
|
||||
<% icon_explanation, icon_aria_label, icon_class = icon_data(context: assignment.context,
|
||||
current_user: @current_user,
|
||||
recent_event: assignment,
|
||||
student_only: true)
|
||||
%>
|
||||
<li class="todo" style="<%= hidden if i >= visible_limit %>">
|
||||
<a
|
||||
class="item tooltip todo-tooltip"
|
||||
href="<%= course_assignment_path( assignment.context_id, assignment.id ) %>#submit"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs submitting"
|
||||
>
|
||||
<% if show_context || assignment.points_possible %>
|
||||
<span class="tooltip_wrap">
|
||||
<span class='tooltip-carat'></span>
|
||||
<span class="tooltip_text">
|
||||
<% if assignment.points_possible %>
|
||||
<span class="screenreader_points_possible" aria-live="true" style="display: block; font-size: 0.8em;"><%= t 'points_possible', 'out of %{points_possible}', :points_possible => assignment.points_possible %></span>
|
||||
<% end %>
|
||||
<% if show_context %>
|
||||
<span style="display: block; font-size: 0.8em;"><%= assignment.context.short_name %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
</span>
|
||||
<% end %>
|
||||
<i class="<%= icon_class %>" aria-label="<%= icon_aria_label %>"></i>
|
||||
<div class="todo-details">
|
||||
<b><%= assignment.submission_action_string %></b>
|
||||
<em><%= translated_due_date(assignment) %></em>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'submitting', :item => assignment } %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% needs_reviewing.each_with_index do |assessment_request, i| %>
|
||||
<% if assessment_request.asset.assignment.published? %>
|
||||
<li class="todo" style="<%= hidden if i >= visible_limit %>">
|
||||
<% assignment = assessment_request.asset.assignment %>
|
||||
<a
|
||||
class="item tooltip"
|
||||
href="<%= course_assignment_submission_path( assignment.context_id, assignment.id, assessment_request.user_id) %>"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs reviewing"
|
||||
data-tooltip
|
||||
title="<%= submission_author_name_for(assessment_request, "#{t('user')}: ") %>"
|
||||
>
|
||||
<i class="icon-peer-review" aria-label="Peer Review"></i>
|
||||
<div class="todo-details">
|
||||
<b>Peer Review for <%= assignment.title %></b>
|
||||
<em>
|
||||
<% if assignment.peer_reviews_due_at %>
|
||||
<%= t('peer_review_due_date', 'due: %{peer_review_due_at}', {:peer_review_due_at => datetime_string(force_zone(assignment.peer_reviews_due_at))}) %>
|
||||
<% else %>
|
||||
<%= t('no_peer_review_due_date', 'due: No Due Date') %>
|
||||
<% end %>
|
||||
</em>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'reviewing', :item => assessment_request} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% hidden_items = [needs_grading.length - visible_limit, 0].max + [needs_submitting.length - visible_limit, 0].max + [needs_reviewing.length - visible_limit, 0].max %>
|
||||
<% if hidden_items > 0 %>
|
||||
<li>
|
||||
<a href="#" class="more_link">
|
||||
<%= t 'links.show_more', '%{count} more...', :count => hidden_items %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -9,7 +9,7 @@
|
|||
if @current_user_submissions
|
||||
submission = @current_user_submissions.detect { |s| s.assignment_id == recent_event.id }
|
||||
elsif @current_user
|
||||
submission = @current_user.submissions.select([:id, :assignment_id, :score, :workflow_state, :updated_at]).where(:assignment_id => recent_event).first
|
||||
submission = @current_user.submissions.select([:id, :assignment_id, :score, :grade, :workflow_state, :updated_at]).where(:assignment_id => recent_event).first
|
||||
end
|
||||
|
||||
if is_assignment
|
||||
|
@ -17,7 +17,8 @@
|
|||
end
|
||||
end
|
||||
|
||||
cache([ 'recent_event_render2',
|
||||
cache([ 'recent_event_render3',
|
||||
@current_user, # needs to be here to bust the cache when the user changes course nicknames
|
||||
submission || 'no_submission',
|
||||
recent_event || 'blank_event',
|
||||
(recent_event.due_at if is_assignment),
|
||||
|
@ -32,50 +33,39 @@
|
|||
:recent_event => recent_event,
|
||||
:submission => submission,
|
||||
:show_assignment_type_icon => true)
|
||||
if is_calendar_event
|
||||
context = recent_event.effective_context
|
||||
else
|
||||
context = recent_event.context
|
||||
end
|
||||
|
||||
%>
|
||||
|
||||
<a
|
||||
data-track-category="dashboard"
|
||||
data-track-label="recent event"
|
||||
class="tooltip" href="<%= recent_event_url(recent_event) %>"
|
||||
href="<%= recent_event_url(recent_event) %>"
|
||||
>
|
||||
<span class="tooltip_wrap">
|
||||
<span class='tooltip-carat'></span>
|
||||
<span class="tooltip_text">
|
||||
<% if is_assignment %>
|
||||
<span style="display: block;"><%= t(:due, "due") %>:
|
||||
<%= due_at(recent_event, @current_user) %>
|
||||
</span>
|
||||
<% if icon_explanation %>
|
||||
<span style="display: block; font-style: italic;"><%= icon_explanation %></span>
|
||||
<% end %>
|
||||
<% if recent_event.points_possible %>
|
||||
<span style="display: block;"><%= t 'submission_score', %{%{score} *out of %{points_possible}*},
|
||||
:score => "<strong>#{render_score(submission.score) if submission && !recent_event.muted?}</strong>".html_safe,
|
||||
:points_possible => recent_event.points_possible,
|
||||
:wrapper => '<span style="font-size: 0.8em;">\1</span>' %></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span style="display: block;"><%= datetime_string(recent_event.start_at, :event, recent_event.end_at) %></span>
|
||||
<% end %>
|
||||
<% if show_context %>
|
||||
<span style="display: block; font-size: 0.8em;">
|
||||
<%= is_calendar_event ? recent_event.effective_context.short_name : recent_event.context.short_name %>
|
||||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</span>
|
||||
<i class="<%= icon_class %>" aria-label="<%= icon_aria_label %>"></i>
|
||||
<div class="event-details">
|
||||
<b><%= recent_event.title %></b>
|
||||
<em>
|
||||
<% if show_context %>
|
||||
<p><%= context.nickname_for(@current_user) %></p>
|
||||
<% end %>
|
||||
<p>
|
||||
<% if is_assignment %>
|
||||
<%= due_at(recent_event, @current_user, 'date') %>
|
||||
<% if submission && readable_grade(submission) && !recent_event.muted? %>
|
||||
<%= readable_grade(submission) %>
|
||||
•
|
||||
<% elsif recent_event.points_possible %>
|
||||
<%= t({one: '1 point', other: '%{count} points'}, count: recent_event.points_possible) %>
|
||||
•
|
||||
<% end %>
|
||||
<%= due_at(recent_event, @current_user) %>
|
||||
<% else %>
|
||||
<%= datetime_string(recent_event.start_at, :short ) %>
|
||||
<%= datetime_string(recent_event.start_at) %>
|
||||
<% end %>
|
||||
</em>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
grade = nil
|
||||
score = nil
|
||||
|
||||
cache(['recent_feedback_render2', recent_feedback || 'blank_feedback', Time.zone.utc_offset].cache_key) do
|
||||
# current user needs to be in the cache key to bust the cache when they change course nicknames
|
||||
cache(['recent_feedback_render3', @current_user, recent_feedback || 'blank_feedback', Time.zone.utc_offset].cache_key) do
|
||||
context = recent_feedback.context
|
||||
assignment = recent_feedback.assignment
|
||||
url = context_url(context, :context_assignment_submission_url, :assignment_id => recent_feedback.assignment_id, :id=>@current_user.id)
|
||||
|
@ -25,42 +26,8 @@
|
|||
<a
|
||||
data-track-category="dashboard"
|
||||
data-track-label="recent feedback"
|
||||
class="recent_feedback_icon tooltip" href="<%= url %>"
|
||||
class="recent_feedback_icon" href="<%= url %>"
|
||||
>
|
||||
<span class="tooltip_wrap">
|
||||
<span class='tooltip-carat'></span>
|
||||
<span class="tooltip_text">
|
||||
<% if recent_feedback.workflow_state != 'unsubmitted' %>
|
||||
<span style="display: block;"><%= before_label(icon_explanation.try(:capitalize)) %>
|
||||
<% if recent_feedback.workflow_state == 'graded' %>
|
||||
<span style="font-size: 0.8em;"><%= datetime_string(recent_feedback.graded_at) %></span>
|
||||
<% else %>
|
||||
<span style="font-size: 0.8em;"><%= datetime_string(recent_feedback.submitted_at) %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<% unless recent_feedback.workflow_state == 'graded' %>
|
||||
<span style="display: block; font-style: italic;"><%= t('not_graded', %{not graded}) %></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span style="display: block; font-style: italic;"><%= icon_explanation.try(:capitalize) %></span>
|
||||
<span style="display: block; font-size: 0.8em;"><%= translated_due_date(assignment) %></span>
|
||||
<% end %>
|
||||
<% if assignment.points_possible %>
|
||||
<span style="display: block;">
|
||||
<% if grade %>
|
||||
<%= t 'submission_points.with_score', %{Score: %{score} *out of %{points_possible}*}, :score => render_score(score), :points_possible => assignment.points_possible,
|
||||
:wrapper => '<span style="font-size: 0.8em;">\1</span>' %>
|
||||
<% else %>
|
||||
<span style="font-size: 0.8em;"><%= t 'submission_points.without_score', "out of %{points_possible}", :points_possible => assignment.points_possible %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<span style="display: block;"><%= t 'comments', "Comments: %{count}", :count => recent_feedback.submission_comments.length %></span>
|
||||
<% if show_context %>
|
||||
<span style="display: block; font-size: 0.8em;"><%= context.short_name %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
</span>
|
||||
<i class="<%= icon_class %>"></i>
|
||||
<div class="event-details">
|
||||
<% if comment && comment.media_comment? %>
|
||||
|
@ -68,18 +35,14 @@
|
|||
<img src="<%= kaltura_thumbnail_url %>" style="float: right; padding-left: 3px;" alt=""/>
|
||||
<% end %>
|
||||
<b class="recent_feedback_title"><%= recent_feedback.assignment.title %></b>
|
||||
<% if comment_text or grade %>
|
||||
<em class="recent_feedback_comment">
|
||||
<% if grade %>
|
||||
<strong><%= grade %></strong>
|
||||
<%= " - " if comment_text && (!comment || !comment.media_comment?) %>
|
||||
<% end %>
|
||||
<% if comment_text %>
|
||||
<span class="<%= 'hidden-readable' if comment && comment.media_comment? %>">
|
||||
“<%= comment_text %>”
|
||||
</span>
|
||||
<% end %>
|
||||
</em>
|
||||
<% if show_context %>
|
||||
<p><%= context.nickname_for(@current_user) %></p>
|
||||
<% end %>
|
||||
<% if grade %>
|
||||
<p><strong><%= grade %></strong></p>
|
||||
<% end %>
|
||||
<% if comment_text %>
|
||||
<p>"<%= comment_text %>"</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
<%
|
||||
# This is rendered both on the dashboard and on the course homepage. On the
|
||||
# dashboard, contexts is nil, and so the cache is only based on the user, which
|
||||
# does not get touched when an assignment needs_grading count changes. So for
|
||||
# the dashboard, we expire after 3 minutes. On the course page, contexts is the
|
||||
# course, which does get touched, and so the cache expiration works.
|
||||
#
|
||||
# BTW if you add a new thing here, it probably needs adding to the /users/self/todo API
|
||||
cache_opts = (contexts.present? ? {} : { :expires_in => 3.minutes })
|
||||
cache(safe_cache_key([@current_user, contexts, 'to_do_list_view']), cache_opts) do
|
||||
hidden_todos = 0
|
||||
presenter = ToDoListPresenter.new(self, @current_user, contexts)
|
||||
%>
|
||||
|
||||
<% if presenter.any_assignments? %>
|
||||
<h2><%= t('headings.to_do', %{To Do}) %></h2>
|
||||
<ul class="right-side-list to-do-list">
|
||||
<% presenter.needs_grading.each_with_index do |assignment, i| %>
|
||||
<li class="todo" style="<%= hidden if i >= presenter.visible_limit %>">
|
||||
<a
|
||||
class="item"
|
||||
href="<%= assignment.gradebook_path %>"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs grading"
|
||||
>
|
||||
<div class="todo-badge-wrapper">
|
||||
<div class="todo-badge">
|
||||
<span aria-hidden="true"><%= assignment.needs_grading_badge %></span>
|
||||
<span class="screenreader-only"><%= assignment.needs_grading_label %></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-details">
|
||||
<b><%= t('Grade %{assignment}', assignment: assignment.title) %></b>
|
||||
<% if presenter.show_context? %>
|
||||
<p><%= assignment.context_name %></p>
|
||||
<% end %>
|
||||
<p>
|
||||
<% if assignment.points_possible %>
|
||||
<%= t({one: '1 point', other: '%{count} points'}, count: assignment.points_possible) %>
|
||||
•
|
||||
<% end %>
|
||||
<%= assignment.formatted_due_date %>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {presenter: assignment} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% presenter.needs_moderation.each_with_index do |assignment, i| %>
|
||||
<% icon_explanation, icon_aria_label, icon_class = assignment.needs_moderation_icon_data %>
|
||||
<li class="todo" style="<%= hidden if i >= presenter.visible_limit %>">
|
||||
<a
|
||||
class="item"
|
||||
href="<%= assignment.moderate_path %>"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs moderation"
|
||||
>
|
||||
<i class="<%= icon_class %>" aria-label="<%= icon_aria_label %>"></i>
|
||||
<div class="todo-details">
|
||||
<b><%= t('Moderate %{assignment}', assignment: assignment.title) %></b>
|
||||
<% if presenter.show_context? %>
|
||||
<p><%= assignment.context_name %></p>
|
||||
<% end %>
|
||||
<p>
|
||||
<% if assignment.points_possible %>
|
||||
<%= t({one: '1 point', other: '%{count} points'}, count: assignment.points_possible) %>
|
||||
•
|
||||
<% end %>
|
||||
<%= assignment.formatted_due_date %>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {presenter: assignment} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% presenter.needs_submitting.each_with_index do |assignment, i| %>
|
||||
<% icon_explanation, icon_aria_label, icon_class = assignment.needs_submitting_icon_data %>
|
||||
<li class="todo" style="<%= hidden if i >= presenter.visible_limit %>">
|
||||
<a
|
||||
class="item"
|
||||
href="<%= assignment.assignment_path %>#submit"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs submitting"
|
||||
>
|
||||
<i class="<%= icon_class %>" aria-label="<%= icon_aria_label %>"></i>
|
||||
<div class="todo-details">
|
||||
<b><%= assignment.submission_action_string %></b>
|
||||
<% if presenter.show_context? %>
|
||||
<p><%= assignment.context_name %></p>
|
||||
<% end %>
|
||||
<p>
|
||||
<% if assignment.points_possible %>
|
||||
<%= t({one: '1 point', other: '%{count} points'}, count: assignment.points_possible) %>
|
||||
•
|
||||
<% end %>
|
||||
<%= assignment.formatted_due_date %>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {presenter: assignment} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% presenter.needs_reviewing.each_with_index do |assessment_request, i| %>
|
||||
<li class="todo" style="<%= hidden if i >= presenter.visible_limit %>">
|
||||
<% assignment = assessment_request.assignment_presenter %>
|
||||
<a
|
||||
class="item"
|
||||
href="<%= assessment_request.submission_path %>"
|
||||
data-track-category="dashboard"
|
||||
data-track-label="todo needs reviewing"
|
||||
title="<%= assessment_request.submission_author_name %>"
|
||||
>
|
||||
<%# Don't need aria-label here because we say that this is a peer review in the text immediately following %>
|
||||
<i class="icon-peer-review"></i>
|
||||
<div class="todo-details">
|
||||
<b><%= t('Peer Review for %{assignment}', assignment: assignment.title) %></b>
|
||||
<% if presenter.show_context? %>
|
||||
<p><%= assessment_request.context_name %></p>
|
||||
<% end %>
|
||||
<p>
|
||||
<% if assignment.try(:points_possible) %>
|
||||
<%= t({one: '1 point', other: '%{count} points'}, count: assignment.points_possible) %>
|
||||
•
|
||||
<% end %>
|
||||
<%= assignment.formatted_peer_review_due_date %>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {presenter: assessment_request} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if presenter.hidden_count > 0 %>
|
||||
<li>
|
||||
<a href="#" class="more_link">
|
||||
<%= t 'links.show_more', '%{count} more...', :count => presenter.hidden_count %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -97,7 +97,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render :partial => 'assignments_needing_grading', :locals => {:contexts => [@context]} %>
|
||||
<%= render :partial => 'to_do_list', :locals => {:contexts => [@context]} %>
|
||||
<%= render :partial => "group_list", :locals => {:group_list => @user_groups} %>
|
||||
<%= nbsp unless @current_user %>
|
||||
</div>
|
||||
|
|
|
@ -1,30 +1,12 @@
|
|||
<%# presenter is a ToDoListPresenter::AssignmentPresenter or a ToDoListPresenter::AssessmentRequestPresenter %>
|
||||
<div class="IgnoreButton al-dropbown__container">
|
||||
<a class="<%= todo_link_classes(type) %>"
|
||||
aria-haspopup="true"
|
||||
title="<%= t('Ignore this assignment') %>"
|
||||
<a class="disable_item_link disable-todo-item-link"
|
||||
title="<%= presenter.ignore_title %>"
|
||||
href="#"
|
||||
data-api-href="<%= todo_ignore_api_url(type, item) %>"
|
||||
data-popup-within="body"
|
||||
data-api-href="<%= presenter.ignore_url %>"
|
||||
data-flash-message="<%= presenter.ignore_flash_message %>"
|
||||
>
|
||||
<i class="icon-x"></i>
|
||||
<span class="screenreader-only"><%= t('Ignore') %></span>
|
||||
</a>
|
||||
|
||||
<% if todo_ignore_dropdown_type?(type) %>
|
||||
<% title = case type.to_sym
|
||||
when :grading
|
||||
t('Ignore Until New Submission')
|
||||
when :moderation
|
||||
t('Ignore Until New Mark')
|
||||
end %>
|
||||
|
||||
<ul id="ignore_dropdown" class="al-options" role="menu" tabindex="0" aria-hidden="true" aria-expanded="false" aria-activedescendant="ignore_dropdown">
|
||||
<li role="presentation">
|
||||
<a href="#" id="ignore_forever" class="icon-trash disable-todo-item-link" tabindex="-1" role="menuitem" data-api-href="<%= todo_ignore_api_url(type, item, true) %>" title="<%= t('Ignore') %>"><%= t('Ignore') %></a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#" id="ignore_until_submission" class="icon-star disable-todo-item-link" tabindex="-1" role="menuitem" data-api-href="<%= todo_ignore_api_url(type, item) %>" title="<%= title %>"><%= title %></a>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
|
@ -5,7 +5,7 @@
|
|||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => 'courses/assignments_needing_grading', :locals => {:contexts => nil} %>
|
||||
<%= render :partial => 'courses/to_do_list', :locals => {:contexts => nil} %>
|
||||
<% locals = {
|
||||
:title => t('coming_up', "Coming Up"),
|
||||
:period => :one_week,
|
||||
|
|
|
@ -853,14 +853,18 @@ define([
|
|||
event.preventDefault();
|
||||
var $item = $(this).parents("li, div.topic_message").last();
|
||||
var $prevItem = $(this).closest('.to-do-list > li').prev()
|
||||
var toFocus = ($prevItem.find('.al-trigger').length && $prevItem.find('.al-trigger')) ||
|
||||
var toFocus = ($prevItem.find('.disable-todo-item-link').length && $prevItem.find('.disable-todo-item-link')) ||
|
||||
$('.event-list-view-calendar')
|
||||
var url = $(this).data('api-href');
|
||||
var flashMessage = $(this).data('flash-message');
|
||||
function remove(delete_url) {
|
||||
$item.confirmDelete({
|
||||
url: delete_url,
|
||||
noMessage: true,
|
||||
success: function() {
|
||||
if (flashMessage) {
|
||||
$.flashMessage(flashMessage);
|
||||
}
|
||||
$(this).slideUp(function() {
|
||||
$(this).remove();
|
||||
toFocus.focus();
|
||||
|
|
|
@ -27,7 +27,7 @@ describe "varied due dates" do
|
|||
|
||||
def assert_coming_up_due_date(response, expected)
|
||||
doc = Nokogiri::HTML(response.body)
|
||||
expect(doc.at_css("#right-side .coming_up .event a .tooltip_text").text).to include(
|
||||
expect(doc.at_css("#right-side .coming_up .event a .event-details").text).to include(
|
||||
expected.is_a?(String) ? expected : datetime_string(expected)
|
||||
)
|
||||
end
|
||||
|
@ -41,7 +41,7 @@ describe "varied due dates" do
|
|||
|
||||
def assert_recent_feedback_due_date(response, expected)
|
||||
doc = Nokogiri::HTML(response.body)
|
||||
expect(doc.at_css("#right-side .recent_feedback .event a .tooltip_text").text).to include(
|
||||
expect(doc.at_css("#right-side .recent_feedback .event a .event-details").text).to include(
|
||||
expected.is_a?(String) ? expected : datetime_string(expected)
|
||||
)
|
||||
end
|
||||
|
@ -151,13 +151,6 @@ describe "varied due dates" do
|
|||
get '/dashboard-sidebar'
|
||||
assert_coming_up_due_date wrap_partial(response), @course_due_date
|
||||
end
|
||||
|
||||
it "shows the course due date in 'recent feedback'" do
|
||||
create_recent_feedback @student1
|
||||
login_as(@student1.pseudonym.login, 'asdfasdf')
|
||||
get '/dashboard-sidebar'
|
||||
assert_recent_feedback_due_date wrap_partial(response), @course_due_date
|
||||
end
|
||||
end
|
||||
|
||||
context "in the overridden section" do
|
||||
|
@ -173,13 +166,6 @@ describe "varied due dates" do
|
|||
get '/dashboard-sidebar'
|
||||
assert_coming_up_due_date wrap_partial(response), @section_due_date
|
||||
end
|
||||
|
||||
it "shows the section due date in 'recent feedback'" do
|
||||
create_recent_feedback @student2
|
||||
login_as(@student2.pseudonym.login, 'asdfasdf')
|
||||
get '/dashboard-sidebar'
|
||||
assert_recent_feedback_due_date wrap_partial(response), @section_due_date
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -48,12 +48,13 @@ describe "dashboard" do
|
|||
due_date = Time.now.utc + 2.days
|
||||
@assignment = assignment_model({:due_at => due_date, :course => @course})
|
||||
get "/"
|
||||
expect(f('.events_list .event a')).to include_text(@assignment.title)
|
||||
event = f('.events_list .event a')
|
||||
expect(event).to include_text(@assignment.title)
|
||||
# use jQuery to get the text since selenium can't figure it out when the elements aren't displayed
|
||||
expect(driver.execute_script("return $('.event a .tooltip_text').text()")).to match(@course.short_name)
|
||||
expect(event).to include_text(@course.short_name)
|
||||
end
|
||||
|
||||
it "should display quiz submissions with essay questions as submitted in coming up list", priority: "1", test_id: 216395 do
|
||||
it "should display quiz submissions with essay questions with points in coming up list", priority: "1", test_id: 216395 do
|
||||
quiz_with_graded_submission([:question_data => {:id => 31,
|
||||
:name => "Quiz Essay Question 1",
|
||||
:question_type => 'essay_question',
|
||||
|
@ -70,9 +71,8 @@ describe "dashboard" do
|
|||
@assignment.save!
|
||||
|
||||
get "/"
|
||||
keep_trying_until { expect(ffj(".events_list .event .tooltip_wrap").size).to be > 0 }
|
||||
driver.execute_script("$('.events_list .event .tooltip_wrap, .events_list .event .tooltip_text').css('visibility', 'visible')")
|
||||
expect(f('.events_list .event .tooltip_wrap')).to include_text 'submitted'
|
||||
keep_trying_until { expect(ffj(".events_list .event-details").size).to be > 0 }
|
||||
expect(f('.events_list .event-details')).to include_text '10 points'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,41 +39,6 @@ describe "dashboard" do
|
|||
end
|
||||
end
|
||||
|
||||
it "should be able to ignore an assignment to grade permanently", priority: "1", test_id: 216398 do
|
||||
assignment = assignment_model({:submission_types => 'online_text_entry', :course => @course})
|
||||
student = user_with_pseudonym(:active_user => true, :username => 'student@example.com', :password => 'qwerty')
|
||||
student2 = user_with_pseudonym(:active_user => true, :username => 'student2@example.com', :password => 'qwerty')
|
||||
@course.enroll_user(student, "StudentEnrollment", :enrollment_state => 'active')
|
||||
@course.enroll_user(student2, "StudentEnrollment", :enrollment_state => 'active')
|
||||
assignment.reload
|
||||
assignment.submit_homework(student, {:submission_type => 'online_text_entry', :body => 'ABC'})
|
||||
assignment.reload
|
||||
enable_cache do
|
||||
get "/"
|
||||
|
||||
f('.to-do-list .disable_item_link').click
|
||||
wait_for_ajaximations
|
||||
f('#ignore_forever').click
|
||||
wait_for_ajaximations
|
||||
expect(f('.to-do-list > li')).to be_nil
|
||||
|
||||
get "/"
|
||||
|
||||
expect(f('.to-do-list')).to be_nil
|
||||
end
|
||||
|
||||
assignment.reload
|
||||
assignment.submit_homework(student2, {:submission_type => 'online_text_entry', :body => 'ABC'})
|
||||
assignment.reload
|
||||
enable_cache do
|
||||
get "/"
|
||||
|
||||
expect(f('.to-do-list')).to be_nil
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it "should be able to ignore an assignment until the next submission", priority: "1", test_id: 216399 do
|
||||
assignment = assignment_model({:submission_types => 'online_text_entry', :course => @course})
|
||||
student = user_with_pseudonym(:active_user => true, :username => 'student@example.com', :password => 'qwerty')
|
||||
|
@ -86,10 +51,8 @@ describe "dashboard" do
|
|||
enable_cache do
|
||||
get "/"
|
||||
|
||||
f('.to-do-list .disable_item_link').click
|
||||
wait_for_ajaximations
|
||||
ignore_link = f('#ignore_until_submission')
|
||||
expect(ignore_link).to include_text("Ignore Until New Submission")
|
||||
ignore_link = f('.to-do-list .disable_item_link')
|
||||
expect(ignore_link['title']).to include_text("Ignore until new submission")
|
||||
ignore_link.click
|
||||
wait_for_ajaximations
|
||||
expect(f('.to-do-list > li')).to be_nil
|
||||
|
@ -162,12 +125,9 @@ describe "dashboard" do
|
|||
get "/"
|
||||
|
||||
ff('.to-do-list .disable_item_link').each do |link|
|
||||
expect(link['title']).to include_text("Ignore until new mark")
|
||||
link.click
|
||||
wait_for_ajaximations
|
||||
ignore_link = f('#ignore_until_submission')
|
||||
expect(ignore_link).to include_text("Ignore Until New Mark")
|
||||
ignore_link.click
|
||||
wait_for_ajaximations
|
||||
end
|
||||
|
||||
expect(f('.to-do-list > li')).to be_nil
|
||||
|
@ -203,8 +163,6 @@ describe "dashboard" do
|
|||
all_todo_links = ff('.to-do-list .disable_item_link')
|
||||
all_todo_links.last.click
|
||||
wait_for_ajaximations
|
||||
ff('#ignore_forever').last.click
|
||||
wait_for_ajaximations
|
||||
|
||||
check_element_has_focus(all_todo_links.first)
|
||||
end
|
||||
|
@ -216,8 +174,6 @@ describe "dashboard" do
|
|||
|
||||
f('.to-do-list .disable_item_link').click
|
||||
wait_for_ajaximations
|
||||
f('#ignore_forever').click
|
||||
wait_for_ajaximations
|
||||
|
||||
check_element_has_focus(f('.event-list-view-calendar'))
|
||||
end
|
||||
|
|
|
@ -38,14 +38,60 @@ describe "/courses/_recent_event" do
|
|||
expect(response.body).to match %r{<b>my assignment</b>}
|
||||
end
|
||||
|
||||
context "assignment muting and tooltips" do
|
||||
it "shows the context when asked to" do
|
||||
course_with_student_logged_in
|
||||
event = @course.calendar_events.create(title: "some assignment", start_at: Time.zone.now)
|
||||
|
||||
render partial: "courses/recent_event", object: event, locals: {is_hidden: false, show_context: true}
|
||||
|
||||
expect(response.body).to include(@course.name)
|
||||
end
|
||||
|
||||
it "doesn't show the context when not asked to" do
|
||||
course_with_student_logged_in
|
||||
event = @course.calendar_events.create(title: "some assignment", start_at: Time.zone.now)
|
||||
|
||||
render partial: "courses/recent_event", object: event, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to_not include(@course.name)
|
||||
end
|
||||
|
||||
context 'assignments' do
|
||||
before do
|
||||
course_with_student(active_all: true)
|
||||
submission_model
|
||||
assigns[:current_user] = @user
|
||||
end
|
||||
|
||||
it 'shows points possible for an ungraded assignment' do
|
||||
render partial: "courses/recent_event", object: @assignment, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to include("#{@assignment.points_possible} points")
|
||||
end
|
||||
|
||||
it 'shows the grade for a graded assignment' do
|
||||
@assignment.grade_student(@user, grade: 7)
|
||||
|
||||
render partial: "courses/recent_event", object: @assignment, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to include("7 out of #{@assignment.points_possible}")
|
||||
end
|
||||
|
||||
it 'shows the due date' do
|
||||
render partial: "courses/recent_event", object: @assignment, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to include(view.datetime_string(@assignment.due_at))
|
||||
end
|
||||
end
|
||||
|
||||
context "assignment muting" do
|
||||
before(:each) do
|
||||
course_with_student
|
||||
view_context
|
||||
@quiz = @course.quizzes.create!
|
||||
@quiz.generate_quiz_data
|
||||
@quiz.workflow_state = 'available'
|
||||
@quiz.published_at = Time.now
|
||||
@quiz.published_at = Time.zone.now
|
||||
@quiz.save
|
||||
expect(@quiz.assignment).not_to be_nil
|
||||
|
||||
|
@ -53,18 +99,18 @@ describe "/courses/_recent_event" do
|
|||
Quizzes::SubmissionGrader.new(@quiz_submission).grade_submission
|
||||
|
||||
@submission = @quiz_submission.submission
|
||||
Submission.any_instance.stubs(:score).returns(1234567890987654400)
|
||||
Submission.any_instance.stubs(:grade).returns(1234567890987654400)
|
||||
end
|
||||
|
||||
it "should show the score for a non-muted assignment" do
|
||||
it "should show the grade for a non-muted assignment" do
|
||||
render :partial => "courses/recent_event", :object => @quiz.assignment, :locals => { :is_hidden => false, :submissions => [ @submission ] }
|
||||
expect(response.body).to match /#{@submission.score}/
|
||||
expect(response.body).to match /#{@submission.grade}/
|
||||
end
|
||||
|
||||
it "should not show the score for a muted assignment" do
|
||||
it "should not show the grade for a muted assignment" do
|
||||
@quiz.assignment.mute!
|
||||
render :partial => "courses/recent_event", :object => @quiz.assignment, :locals => { :is_hidden => false, :submissions => [ @submission ] }
|
||||
expect(response.body).not_to match /#{@submission.score}/
|
||||
expect(response.body).not_to match /#{@submission.grade}/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../views_helper')
|
||||
|
||||
describe "/courses/_recent_feedback" do
|
||||
before do
|
||||
course_with_student(active_all: true)
|
||||
assigns[:current_user] = @user
|
||||
submission_model
|
||||
end
|
||||
|
||||
it 'shows the context when asked to' do
|
||||
@assignment.grade_student(@user, grade: 7)
|
||||
@submission.reload
|
||||
|
||||
render partial: "courses/recent_feedback", object: @submission, locals: {is_hidden: false, show_context: true}
|
||||
|
||||
expect(response.body).to include(@course.name)
|
||||
end
|
||||
|
||||
it "doesn't show the context when not asked to" do
|
||||
@assignment.grade_student(@user, grade: 7)
|
||||
@submission.reload
|
||||
|
||||
render partial: "courses/recent_feedback", contexts: [@course], object: @submission, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to_not include(@course.name)
|
||||
end
|
||||
|
||||
it 'shows the comment' do
|
||||
@assignment.grade_student(@user, comment: 'bunch of random stuff', grader: @teacher)
|
||||
@submission.reload
|
||||
|
||||
render partial: "courses/recent_feedback", object: @submission, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to include('bunch of random stuff')
|
||||
end
|
||||
|
||||
it 'shows the grade' do
|
||||
@assignment.grade_student(@user, grade: 5782394)
|
||||
@submission.reload
|
||||
|
||||
render :partial => "courses/recent_feedback", object: @submission, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to include("5782394 out of #{@assignment.points_possible}")
|
||||
end
|
||||
|
||||
it 'shows the grade and the comment' do
|
||||
@assignment.grade_student(@user, grade: 25734, comment: 'something different', grader: @teacher)
|
||||
@submission.reload
|
||||
|
||||
render :partial => "courses/recent_feedback", object: @submission, locals: {is_hidden: false}
|
||||
|
||||
expect(response.body).to include("25734 out of #{@assignment.points_possible}")
|
||||
expect(response.body).to include('something different')
|
||||
end
|
||||
end
|
|
@ -0,0 +1,125 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../views_helper')
|
||||
|
||||
describe "courses/_to_do_list.html.erb" do
|
||||
include AssignmentsHelper
|
||||
|
||||
context "as a student" do
|
||||
describe "assignments due" do
|
||||
it "shows assignment data" do
|
||||
course_with_student(active_all: true)
|
||||
@user.course_nicknames[@course.id] = "My Awesome Course"
|
||||
@user.save!
|
||||
due_date = 2.days.from_now
|
||||
assignment_model(course: @course,
|
||||
due_at: due_date,
|
||||
submission_types: "online_text_entry",
|
||||
points_possible: 15,
|
||||
title: "SubmitMe")
|
||||
view_context
|
||||
# title, course nickname, points, due date
|
||||
render partial: "courses/to_do_list", locals: {contexts: nil}
|
||||
expect(response).to include "Turn in SubmitMe"
|
||||
expect(response).to include "15 points"
|
||||
expect(response).to include "My Awesome Course"
|
||||
expect(response).to include due_at(@assignment, @user)
|
||||
end
|
||||
end
|
||||
describe "submissions to review" do
|
||||
it "shows peer reviews" do
|
||||
course(active_all: true)
|
||||
due_date = 2.days.from_now
|
||||
assignment_model(course: @course,
|
||||
due_at: due_date,
|
||||
submission_types: "online_text_entry",
|
||||
points_possible: 15,
|
||||
title: "ReviewMe",
|
||||
peer_reviews: true)
|
||||
@submission = submission_model(assignment: @assignment, body: "my submission")
|
||||
@submitter = @user
|
||||
@assessor_submission = submission_model(assignment: @assignment, user: @user, body: "my other submission")
|
||||
@assessor = @user
|
||||
@assessor.course_nicknames[@course.id] = "My Awesome Course"
|
||||
@assessor.save!
|
||||
@assessment_request = AssessmentRequest.create!(assessor: @assessor, asset: @submission, user: @submitter, assessor_asset: @assessor_submission)
|
||||
@assessment_request.workflow_state = "assigned"
|
||||
@assessment_request.save!
|
||||
view_context
|
||||
render partial: "courses/to_do_list", locals: {contexts: nil}
|
||||
expect(response).to include "Peer Review for ReviewMe"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "as a teacher" do
|
||||
describe "assignments to grade" do
|
||||
it "shows assignment data" do
|
||||
course_with_student(active_all: true)
|
||||
due_date = 2.days.from_now
|
||||
assignment_model(course: @course,
|
||||
due_at: due_date,
|
||||
submission_types: "online_text_entry",
|
||||
points_possible: 15,
|
||||
title: "GradeMe",
|
||||
needs_grading_count: 7)
|
||||
@user = @teacher
|
||||
@user.course_nicknames[@course.id] = "My Awesome Course"
|
||||
@user.save!
|
||||
view_context
|
||||
# title, course nickname, points, due date, number of submissions to grade
|
||||
render partial: "courses/to_do_list", locals: {contexts: nil}
|
||||
expect(response).to include "Grade GradeMe"
|
||||
expect(response).to include "15 points"
|
||||
expect(response).to include "My Awesome Course"
|
||||
expect(response).to include due_at(@assignment, @user)
|
||||
expect(response).to include "7"
|
||||
expect(response).to include "7 submissions need grading"
|
||||
end
|
||||
|
||||
it "shows 9+ when there are more than 9 to grade" do
|
||||
course_with_student(active_all: true)
|
||||
due_date = 2.days.from_now
|
||||
assignment_model(course: @course,
|
||||
due_at: due_date,
|
||||
submission_types: "online_text_entry",
|
||||
points_possible: 15,
|
||||
title: "GradeMe",
|
||||
needs_grading_count: 10)
|
||||
@user = @teacher
|
||||
@user.course_nicknames[@course.id] = "My Awesome Course"
|
||||
@user.save!
|
||||
view_context
|
||||
# title, course nickname, points, due date, number of submissions to grade
|
||||
render partial: "courses/to_do_list", locals: {contexts: nil}
|
||||
expect(response).to include "Grade GradeMe"
|
||||
expect(response).to include "15 points"
|
||||
expect(response).to include "My Awesome Course"
|
||||
expect(response).to include due_at(@assignment, @user)
|
||||
expect(response).to include "9+"
|
||||
expect(response).to include "More than 9 submissions need grading"
|
||||
end
|
||||
end
|
||||
|
||||
describe "assignments to moderate" do
|
||||
it "shows assignment data" do
|
||||
course_with_student(active_all: true)
|
||||
due_date = 2.days.from_now
|
||||
assignment_model(course: @course,
|
||||
due_at: due_date,
|
||||
submission_types: "online_text_entry",
|
||||
points_possible: 15,
|
||||
title: "ModerateMe",
|
||||
moderated_grading: true,
|
||||
needs_grading_count: 1)
|
||||
@submission = submission_model(assignment: @assignment, body: "my submission")
|
||||
@submission.find_or_create_provisional_grade!(scorer: @teacher, grade: 5)
|
||||
@user = @teacher
|
||||
@user.course_nicknames[@course.id] = "My Awesome Course"
|
||||
@user.save!
|
||||
view_context
|
||||
render partial: "courses/to_do_list", locals: {contexts: nil}
|
||||
expect(response).to include "Moderate ModerateMe"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue