[a11y] Adds context to module level buttons
Makes it so that screenreaders are given specific module context i.e., the module name, whenever they navigation to a module level button fixes CNVS-22866 Test Plan: - Go to the modules page - Using a screenreader go to the publish cloud at the module level. - It should indicate the name of the module, for example: "Published. Click to unpublish My Cool Module." - Similar things should occur for the Add content button and the manage module dropdown. - The publish button and cog buttons for items within modules should similarly give context. Change-Id: I1ba3f5e5c09e8186667af38eb19852295d5f01e2 Reviewed-on: https://gerrit.instructure.com/63049 Product-Review: Aaron Cannon <acannon@instructure.com> Reviewed-by: Sterling Cobb <sterling@instructure.com> Tested-by: Jenkins QA-Review: Clare Strong <clare@instructure.com>
This commit is contained in:
parent
f53907c0dd
commit
60d3834e9d
|
@ -16,6 +16,7 @@ define [
|
|||
published: true
|
||||
publishable: true
|
||||
unpublishable: true
|
||||
module_item_name: null
|
||||
|
||||
branch: (key) ->
|
||||
(@[key][@get('module_type')] or @[key].generic).call(this)
|
||||
|
@ -45,10 +46,24 @@ define [
|
|||
module: -> module: @attributes
|
||||
|
||||
disabledMessages:
|
||||
generic: -> I18n.t('disabled', 'Publishing is disabled for this item')
|
||||
assignment: -> I18n.t('disabled_assignment', "Can't unpublish if there are student submissions")
|
||||
quiz: -> I18n.t('disabled_quiz', "Can't unpublish if there are student submissions")
|
||||
discussion_topic: -> I18n.t('disabled_discussion_topic', "Can't unpublish if there are student submissions")
|
||||
generic: -> if @get('module_item_name')
|
||||
I18n.t('Publishing %{item_name} is disabled', {item_name: @get('module_item_name')})
|
||||
else
|
||||
I18n.t('Publishing is disabled for this item')
|
||||
|
||||
assignment: -> if @get('module_item_name')
|
||||
I18n.t("Can't unpublish %{item_name} if there are student submissions", {item_name: @get('module_item_name')})
|
||||
else
|
||||
I18n.t("Can't unpublish if there are student submissions")
|
||||
|
||||
quiz: -> if @get('module_item_name')
|
||||
I18n.t("Can't unpublish %{item_name} if there are student submissions", {item_name: @get('module_item_name')})
|
||||
else
|
||||
I18n.t("Can't unpublish if there are student submissions")
|
||||
discussion_topic: -> if @get('module_item_name')
|
||||
I18n.t("Can't unpublish %{item_name} if there are student submissions", {item_name: @get('module_item_name')})
|
||||
else
|
||||
I18n.t("Can't unpublish if there are student submissions")
|
||||
|
||||
publish: ->
|
||||
@save 'published', yes
|
||||
|
|
|
@ -16,6 +16,7 @@ define [
|
|||
togglePublishClassOn: React.PropTypes.object
|
||||
model: customPropTypes.filesystemObject
|
||||
userCanManageFilesForContext: React.PropTypes.bool.isRequired
|
||||
fileName: React.PropTypes.string
|
||||
|
||||
# == React Functions == #
|
||||
getInitialState: -> @extractStateFromModel( @props.model )
|
||||
|
|
|
@ -13,6 +13,10 @@ define [
|
|||
publishedClass: 'btn-published'
|
||||
unpublishClass: 'btn-unpublish'
|
||||
|
||||
# These values allow the default text to be overridden if necessary
|
||||
@optionProperty 'publishText'
|
||||
@optionProperty 'unpublishText'
|
||||
|
||||
tagName: 'button'
|
||||
className: 'btn'
|
||||
|
||||
|
@ -55,7 +59,7 @@ define [
|
|||
|
||||
addAriaLabel: (label) ->
|
||||
$label = @$el.find('span.screenreader-only.accessible_label')
|
||||
$('<span class="screenreader-only accessible_label"></span>').appendTo(@$el) unless $label.length
|
||||
$label = $('<span class="screenreader-only accessible_label"></span>').appendTo(@$el) unless $label.length
|
||||
|
||||
$label.text label
|
||||
@$el.attr 'aria-label', label
|
||||
|
@ -134,14 +138,14 @@ define [
|
|||
renderPublish: ->
|
||||
@renderState
|
||||
text: I18n.t 'buttons.publish', 'Publish'
|
||||
label: I18n.t 'buttons.publish_desc', 'Unpublished. Click to publish.'
|
||||
label: @publishText || I18n.t 'Unpublished. Click to publish.'
|
||||
buttonClass: @publishClass
|
||||
iconClass: 'icon-unpublish'
|
||||
|
||||
renderPublished: ->
|
||||
@renderState
|
||||
text: I18n.t 'buttons.published', 'Published'
|
||||
label: I18n.t 'buttons.published_desc', 'Published. Click to unpublish.'
|
||||
label: @unpublishText || I18n.t 'Published. Click to unpublish.'
|
||||
buttonClass: @publishedClass
|
||||
iconClass: 'icon-publish'
|
||||
|
||||
|
|
|
@ -11,7 +11,12 @@ define [
|
|||
tagName: 'span'
|
||||
className: 'publish-icon'
|
||||
|
||||
# These values allow the default text to be overridden if necessary
|
||||
@optionProperty 'publishText'
|
||||
@optionProperty 'unpublishText'
|
||||
|
||||
initialize: ->
|
||||
super
|
||||
@events = _.extend({}, PublishButtonView.prototype.events, @events)
|
||||
|
||||
events: {'keyclick' : 'click'}
|
||||
|
|
|
@ -30,6 +30,7 @@ define([
|
|||
};
|
||||
|
||||
PublishCloud.render = function () {
|
||||
var fileName = this.props.fileName || I18n.t('This file');
|
||||
if (this.props.userCanManageFilesForContext) {
|
||||
if (this.state.published && this.state.restricted) {
|
||||
return (
|
||||
|
@ -40,7 +41,7 @@ define([
|
|||
ref='publishCloud'
|
||||
className='btn-link published-status restricted'
|
||||
title={this.getRestrictedText()}
|
||||
aria-label={this.getRestrictedText() + ' - ' + I18n.t('Click to modify')}
|
||||
aria-label={`${fileName} is ${this.getRestrictedText()} - ${I18n.t('Click to modify')}`}
|
||||
>
|
||||
<i className='icon-cloud-lock' />
|
||||
</button>
|
||||
|
@ -54,7 +55,7 @@ define([
|
|||
ref='publishCloud'
|
||||
className='btn-link published-status hiddenState'
|
||||
title={I18n.t('Hidden. Available with a link')}
|
||||
aria-label={I18n.t('Hidden. Available with a link - Click to modify')}
|
||||
aria-label={`${fileName} is ${I18n.t('Hidden. Available with a link - Click to modify')}`}
|
||||
>
|
||||
<i className='icon-cloud-lock' />
|
||||
</button>
|
||||
|
@ -68,7 +69,7 @@ define([
|
|||
ref='publishCloud'
|
||||
className='btn-link published-status published'
|
||||
title={I18n.t('Published')}
|
||||
aria-label={I18n.t('Published - Click to modify')}
|
||||
aria-label={`${fileName} is ${I18n.t('Published - Click to modify')}`}
|
||||
>
|
||||
<i className='icon-publish' />
|
||||
</button>
|
||||
|
@ -82,7 +83,7 @@ define([
|
|||
ref='publishCloud'
|
||||
className='btn-link published-status unpublished'
|
||||
title={I18n.t('Unpublished')}
|
||||
aria-label={I18n.t('Unpublished - Click to modify')}
|
||||
aria-label={`${fileName} is ${I18n.t('Unpublished - Click to modify')}`}
|
||||
>
|
||||
<i className='icon-unpublish' />
|
||||
</button>
|
||||
|
@ -97,7 +98,7 @@ define([
|
|||
ref='publishCloud'
|
||||
className='published-status restricted'
|
||||
title={this.getRestrictedText()}
|
||||
aria-label={this.getRestrictedText()}
|
||||
aria-label={`${fileName} is ${this.getRestrictedText()}`}
|
||||
>
|
||||
<i className='icon-calendar-day' />
|
||||
</div>
|
||||
|
|
|
@ -115,6 +115,8 @@
|
|||
data-course-id="<%= context_module && context_module.context_id %>"
|
||||
data-published="<%= published_status == 'published' %>"
|
||||
data-publishable="<%= true %>"
|
||||
data-publish-message="<%= t('Unpublished. Click to publish %{module_name}.', {module_name: context_module ? context_module.name : 'module'}) %>"
|
||||
data-unpublish-message="<%= t('Published. Click to unpublish %{module_name}.', {module_name: context_module ? context_module.name : 'module'}) %>"
|
||||
title=""
|
||||
data-tooltip
|
||||
class="publish-icon module <%= published_status %>"
|
||||
|
@ -123,10 +125,10 @@
|
|||
</span>
|
||||
|
||||
<button
|
||||
aria-label="<%= t('aria_labels.add_item', %{Add Content}) %>"
|
||||
aria-label="<%= t('Add Content to %{module_name}', {module_name: context_module ? context_module.name : 'module'}) %>"
|
||||
rel="<%= context_url(@context, :context_url) %>/modules/<%= context_module ? context_module.id : "{{ id }}" %>/items"
|
||||
class="add_module_item_link btn"><i class="icon-plus"></i><span class="screenreader-only"><%= t('links.add_item', %{Add Content}) %></span></button>
|
||||
<button class="btn al-trigger" aria-label="<%= t("manager_module", "Manage module") %>">
|
||||
class="add_module_item_link btn"><i class="icon-plus"></i><span class="screenreader-only"><%= t('Add Content to %{module_name}', {module_name: context_module ? context_module.name : 'module'}) %></span></button>
|
||||
<button class="btn al-trigger" aria-label="<%= t('Manage %{module_name}', {module_name: context_module ? context_module.name : 'module'}) %>">
|
||||
<i class="icon-settings"></i><i class="icon-mini-arrow-down"></i>
|
||||
</button>
|
||||
<ul class="al-options">
|
||||
|
|
|
@ -115,6 +115,7 @@
|
|||
<% if editable || module_item.nil? %>
|
||||
<div class="ig-admin">
|
||||
<span
|
||||
data-module-item-name="<%= tag && tag.title %>"
|
||||
data-module-type="<%= module_item && module_item.content_type_class %>"
|
||||
data-content-id="<%= module_item && module_item.content_id %>"
|
||||
data-id="<%= module_item_publishable_id(module_item) %>"
|
||||
|
@ -124,6 +125,8 @@
|
|||
data-published="<%= module_item && published_status == 'published' %>"
|
||||
data-publishable="<%= module_item_publishable?(module_item) %>"
|
||||
data-unpublishable="<%= module_item_unpublishable?(module_item) %>"
|
||||
data-publish-message="<%= t('Unpublished. Click to publish %{item_name}.', {item_name: tag && tag.title ? tag.title : ''}) %>"
|
||||
data-unpublish-message="<%= t('Published. Click to unpublish %{item_name}.', {item_name: tag && tag.title ? tag.title : ''}) %>"
|
||||
title=""
|
||||
data-tooltip
|
||||
class="publish-icon <%= published_status %>"
|
||||
|
@ -134,7 +137,7 @@
|
|||
<div class="inline-block cog-menu-container">
|
||||
<a class="al-trigger al-trigger-gray" role="button" tabindex="0" href="#">
|
||||
<i class="icon-settings"></i><i class="icon-mini-arrow-down"></i>
|
||||
<span class="screenreader-only"><%= t('settings', 'Settings') %></span>
|
||||
<span class="screenreader-only"><%= t('Manage %{item_name}', {item_name: tag && tag.title ? tag.title : 'item'}) %></span>
|
||||
</a>
|
||||
|
||||
<ul class="al-options">
|
||||
|
|
|
@ -1323,6 +1323,7 @@ define([
|
|||
var publishData = {
|
||||
moduleType: data.type,
|
||||
id: data.publishable_id,
|
||||
moduleItemName: data.moduleItemName,
|
||||
moduleId: data.context_module_id,
|
||||
courseId: data.context_id,
|
||||
published: data.published,
|
||||
|
@ -1376,7 +1377,8 @@ define([
|
|||
model: file,
|
||||
togglePublishClassOn: $el.parents('.ig-row')[0],
|
||||
userCanManageFilesForContext: ENV.MODULE_FILE_PERMISSIONS.manage_files,
|
||||
usageRightsRequiredForContext: ENV.MODULE_FILE_PERMISSIONS.usage_rights_required
|
||||
usageRightsRequiredForContext: ENV.MODULE_FILE_PERMISSIONS.usage_rights_required,
|
||||
fileName: file.displayName()
|
||||
}
|
||||
|
||||
React.render(PublishCloud(props), $el[0]);
|
||||
|
@ -1389,13 +1391,26 @@ define([
|
|||
id: data.id,
|
||||
module_id: data.moduleId,
|
||||
module_item_id: data.moduleItemId,
|
||||
module_item_name: data.moduleItemName,
|
||||
course_id: data.courseId,
|
||||
published: data.published,
|
||||
publishable: data.publishable,
|
||||
unpublishable: data.unpublishable
|
||||
});
|
||||
|
||||
var view = new PublishIconView({model: model, el: $el[0]});
|
||||
var viewOptions = {
|
||||
model: model,
|
||||
el: $el[0]
|
||||
};
|
||||
|
||||
if (data.publishMessage) {
|
||||
viewOptions.publishText = data.publishMessage;
|
||||
}
|
||||
if (data.unpublishMessage) {
|
||||
viewOptions.unpublishText = data.unpublishMessage;
|
||||
}
|
||||
|
||||
var view = new PublishIconView(viewOptions);
|
||||
var row = $el.closest('.ig-row');
|
||||
|
||||
if (data.published) { row.addClass('ig-published'); }
|
||||
|
|
|
@ -50,6 +50,24 @@ define [
|
|||
equal btnView.$text.html().match(/Published/).length, 1
|
||||
equal btnView.$el.attr('aria-label').match(/can't unpublish/).length, 1
|
||||
|
||||
test 'should render the provided publish text when given', ->
|
||||
testText = 'Test Publish Text'
|
||||
btnView = new PublishButtonView({
|
||||
model: @publish,
|
||||
publishText: testText
|
||||
}).render()
|
||||
|
||||
equal btnView.$('.screenreader-only.accessible_label').text(), testText
|
||||
|
||||
test 'should render the provided unpublish text when given', ->
|
||||
testText = 'Test Unpublish Text'
|
||||
btnView = new PublishButtonView({
|
||||
model: @published,
|
||||
unpublishText: testText
|
||||
}).render()
|
||||
|
||||
equal btnView.$('.screenreader-only.accessible_label').text(), testText
|
||||
|
||||
# state
|
||||
test 'disable should add disabled state', ->
|
||||
btnView = new PublishButtonView(model: @publish).render()
|
||||
|
|
|
@ -41,7 +41,7 @@ describe 'editing a quiz' do
|
|||
type_in_tiny('#quiz_description', 'changed description')
|
||||
click_save_settings_button
|
||||
wait_for_ajax_requests
|
||||
expect(f('#quiz-publish-link').text.strip!).to eq 'Published'
|
||||
expect(f('#quiz-publish-link .publish-text').text.strip!).to eq 'Published'
|
||||
end
|
||||
|
||||
it 'deletes the quiz', priority: "1", test_id: 351921 do
|
||||
|
@ -54,7 +54,7 @@ describe 'editing a quiz' do
|
|||
end
|
||||
f('#quiz-publish-link').click
|
||||
wait_for_ajax_requests
|
||||
expect(f('#quiz-publish-link').text.strip!).to eq 'Publish'
|
||||
expect(f('#quiz-publish-link .publish-text').text.strip!).to eq 'Publish'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -90,7 +90,7 @@ describe 'editing a quiz' do
|
|||
end
|
||||
f('#quiz-publish-link').click
|
||||
wait_for_ajax_requests
|
||||
expect(f('#quiz-publish-link').text.strip!).to eq 'Unpublish'
|
||||
expect(f('#quiz-publish-link .publish-text').text.strip!).to eq 'Unpublish'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue