Fix a11y with the ignore feature of the To Do list
fixes CNVS-19205 Test Plan: - Add a submission to a course that needs grading. - As a teacher of the course go to your dashboard - In the to do list, use a SR to access the menu that pops up with the Ignore "X". - You should be able to navigate it without problem - The same behavior should occur from the course home page. - For keyboard only, focus should go to the previous ignore "X" if it is there. - If a previous ignore "X" isn't available, it should go to the view calendar link. Change-Id: I8e8297dc41ac8af69131ef748f25f169541c2958 Reviewed-on: https://gerrit.instructure.com/50278 Reviewed-by: Dan Minkevitch <dan@instructure.com> Tested-by: Jenkins QA-Review: Clare Strong <clare@instructure.com> Product-Review: Clay Diffrient <cdiffrient@instructure.com>
This commit is contained in:
parent
a9512faebf
commit
5c5baf1113
|
@ -138,4 +138,19 @@ module DashboardHelper
|
|||
end
|
||||
end
|
||||
|
||||
def todo_ignore_api_url(activity_type, item, force_permanent = false)
|
||||
activity_symbol = activity_type.to_sym
|
||||
|
||||
permanent = (activity_symbol != :grading || force_permanent) ? 1 : nil
|
||||
|
||||
api_v1_users_todo_ignore_url(item.asset_string, activity_type, { permanent: permanent })
|
||||
end
|
||||
|
||||
def todo_link_classes(activity_type)
|
||||
activity_symbol = activity_type.to_sym
|
||||
|
||||
(activity_symbol == :grading) ? 'al-trigger disable_item_link' : 'disable_item_link disable-todo-item-link'
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -47,10 +47,7 @@ cache(safe_cache_key([@current_user, contexts, 'a_need_grading']), cache_opts) d
|
|||
<%= t 'need_grading_count', { one: '1 needs grading', other: '%{count} need grading' }, count: Assignments::NeedsGradingCountQuery.new(assignment, @current_user).count %>
|
||||
</em>
|
||||
</a>
|
||||
<a class='disable_item_link grading' title="<%= t('links.title.ignore', %{Ignore this assignment}) %>" href="#" data-api-href="<%= api_v1_users_todo_ignore_url(assignment.asset_string, 'grading') %>">
|
||||
<span class="screenreader-only"><%= t('images.alt.ignore', 'ignore') %></span>
|
||||
<i class="icon-x"></i>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'grading', :item => assignment } %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% needs_submitting.each_with_index do |assignment, i| %>
|
||||
|
@ -77,10 +74,7 @@ cache(safe_cache_key([@current_user, contexts, 'a_need_grading']), cache_opts) d
|
|||
<b><%= assignment.submission_action_string %></b>
|
||||
<em><%= translated_due_date(assignment) %></em>
|
||||
</a>
|
||||
<a class='disable_item_link submitting' title="<%= t('links.title.ignore', %{Ignore this assignment}) %>" href="#" data-api-href="<%= api_v1_users_todo_ignore_url(assignment.asset_string, 'submitting') %>">
|
||||
<span class="screenreader-only"><%= t('images.alt.ignore', 'ignore') %></span>
|
||||
<i class="icon-x"></i>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'submitting', :item => assignment } %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% needs_reviewing.each_with_index do |assessment_request, i| %>
|
||||
|
@ -103,10 +97,7 @@ cache(safe_cache_key([@current_user, contexts, 'a_need_grading']), cache_opts) d
|
|||
<%= t('no_peer_review_due_date', 'due: No Due Date') %>
|
||||
<% end %>
|
||||
</em>
|
||||
<a class='disable_item_link submitting' title="<%= t('links.title.ignore_review', %{Ignore this review}) %>" href="#" data-api-href="<%= api_v1_users_todo_ignore_url(assessment_request.asset_string, 'reviewing') %>">
|
||||
<span class="screenreader-only"><%= t('images.alt.ignore', 'ignore') %></span>
|
||||
<i class="icon-x"></i>
|
||||
</a>
|
||||
<%= render :partial => 'shared/ignore_option_list', :locals => {:type => 'reviewing', :item => assessment_request} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<div class="IgnoreButton al-dropbown__container">
|
||||
<a class="<%= todo_link_classes(type) %>"
|
||||
aria-haspopup="true"
|
||||
title="<%= t('Ignore this assignment') %>"
|
||||
href="#"
|
||||
data-api-href="<%= todo_ignore_api_url(type, item) %>"
|
||||
data-popup-within="body"
|
||||
>
|
||||
<i class="icon-x"></i>
|
||||
<span class="screenreader-only"><%= t('Ignore') %></span>
|
||||
</a>
|
||||
|
||||
<% if type.to_sym == :grading %>
|
||||
<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 Forever') %>"><%= t('Ignore Forever') %></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="<%= t('Ignore Until New Submission') %>"><%= t('Ignore Until New Submission') %></a>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
|
@ -863,9 +863,13 @@ define([
|
|||
}
|
||||
return false;
|
||||
});
|
||||
$("#right-side, #topic_list").delegate('.disable_item_link', 'click', function(event) {
|
||||
|
||||
$('#right-side').on('click', '.disable-todo-item-link', function (event) {
|
||||
event.preventDefault();
|
||||
var $item = $(this).parents("li, div.topic_message");
|
||||
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')) ||
|
||||
$('.event-list-view-calendar')
|
||||
var url = $(this).data('api-href');
|
||||
function remove(delete_url) {
|
||||
$item.confirmDelete({
|
||||
|
@ -874,20 +878,16 @@ define([
|
|||
success: function() {
|
||||
$(this).slideUp(function() {
|
||||
$(this).remove();
|
||||
toFocus.focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if($(this).hasClass('grading')) {
|
||||
options = {}
|
||||
options['<span class="ui-icon ui-icon-trash"> </span> ' + htmlEscape(I18n.t('ignore_forever', 'Ignore Forever'))] = function() { remove(url + "?permanent=1"); };
|
||||
options['<span class="ui-icon ui-icon-star"> </span> ' + htmlEscape(I18n.t('ignore_until_new_submission', 'Ignore Until New Submission'))] = function() { remove(url); };
|
||||
$(this).dropdownList({ options: options });
|
||||
} else {
|
||||
remove(url + "?permanent=1");
|
||||
}
|
||||
|
||||
remove(url);
|
||||
});
|
||||
|
||||
|
||||
// in 2 seconds (to give time for everything else to load), find all the external links and add give them
|
||||
// the external link look and behavior (force them to open in a new tab)
|
||||
setTimeout(function() {
|
||||
|
|
|
@ -19,6 +19,16 @@ define([
|
|||
'jquery' /* $ */
|
||||
], function($) {
|
||||
|
||||
/**
|
||||
* TL;DR: Remove this file when possible.
|
||||
*
|
||||
* Please note that this file is considered very legacy. All instances of it
|
||||
* should be evaluated and replaced with the newer and far better looking
|
||||
* KyleMenu. The only other place that I've seen it in used is the file
|
||||
* attendance.js which is on the chopping block at some point in the future.
|
||||
* Once that file has been axed, then this file should be able to be removed.
|
||||
*/
|
||||
|
||||
// Simple dropdown list. Takes the list of attributes specified in "options" and displays them
|
||||
// in a menu anchored to the selected element.
|
||||
$.fn.dropdownList = function(options) {
|
||||
|
|
|
@ -36,6 +36,114 @@ describe "dashboard" do
|
|||
end
|
||||
end
|
||||
|
||||
it "should be able to ignore an assignment to grade permanently" 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" 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_until_submission').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 > li')).to include_text('Grade ' + assignment.title)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "Todo Ignore Options Focus Management" do
|
||||
before :each do
|
||||
assignment = assignment_model({:submission_types => 'online_text_entry', :course => @course})
|
||||
@student = user_with_pseudonym(:active_user => true, :username => 'student@example.com', :password => 'qwerty')
|
||||
@course.enroll_user(@student, "StudentEnrollment", :enrollment_state => 'active')
|
||||
assignment.submit_homework(@student, {:submission_type => 'online_text_entry', :body => 'ABC'})
|
||||
end
|
||||
|
||||
it "should focus on the previous ignore link after ignoring a todo item" do
|
||||
assignment2 = assignment_model({:submission_types => 'online_text_entry', :course => @course})
|
||||
assignment2.submit_homework(@student, {:submission_type => 'online_text_entry', :body => 'Number2'})
|
||||
enable_cache do
|
||||
get "/"
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
it "should focus on the 'View Calendar' link if there are no other todo items" do
|
||||
enable_cache do
|
||||
get "/"
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
it "should not display assignment to grade in to do list for a designer" do
|
||||
course_with_designer_logged_in(:active_all => true)
|
||||
assignment = assignment_model({:submission_types => 'online_text_entry', :course => @course})
|
||||
|
|
|
@ -59,5 +59,26 @@ describe "dashboard" do
|
|||
expect(f('.to-do-list')).to be_nil
|
||||
expect(f('.coming_up')).to_not include_text(assignment.title)
|
||||
end
|
||||
|
||||
it "should allow to do list items to be ignored" do
|
||||
notification_model(:name => 'Assignment Due Date Changed')
|
||||
notification_policy_model(:notification_id => @notification.id)
|
||||
assignment = assignment_model({:submission_types => 'online_text_entry', :course => @course})
|
||||
assignment.due_at = Time.now + 60
|
||||
assignment.created_at = 1.month.ago
|
||||
assignment.save!
|
||||
|
||||
get "/"
|
||||
|
||||
expect(f('.to-do-list > li')).to include_text(assignment.submission_action_string)
|
||||
f('.to-do-list .disable_item_link').click
|
||||
wait_for_ajaximations
|
||||
expect(f('.to-do-list > li')).to be_nil
|
||||
|
||||
get "/"
|
||||
|
||||
expect(f('.to-do-list')).to be_nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue