Skip to content

Commit 2baf369

Browse files
author
John Corrigan
committed
render table of data from line graph for screen readers
fixes CNVS-19344 - Add template for table. - Update OutcomeSmmaryCollection::ResultCollection#scoresFor method to parse the datetime values from the API. - Update OutcomeLineGraphView#render to render table of data in addition to the d3 driven line graph. - Update OutconeLineGraph to accept a pre-parsed date. test plan: - Navigate to student outcome view at /courses/:course_id/grades/:user_id#tab-outcomes. - Use the keyboard to highlight the `...` icon and hit enter to expand mastery info for an outcome. - Use a screen reader to navigate content in the popover; note the table that is present to explain the information that is otherwise displayed just visually as a line graph. The data features two columns: the first is the data the assignment related to the outcome was submitted or the data the outcome assessment was made; the second is the score the user recieved. Change-Id: Ibc4ac867c8376e1cb9022a06a311b95a2cf27178 Reviewed-on: https://gerrit.instructure.com/51088 Tested-by: Jenkins QA-Review: Adam Stone <astone@instructure.com> Reviewed-by: Simon Williams <simon@instructure.com> Product-Review: Aaron Cannon <acannon@instructure.com>
1 parent 666a791 commit 2baf369

5 files changed

Lines changed: 83 additions & 12 deletions

File tree

app/coffeescripts/collections/OutcomeSummaryCollection.coffee

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ define [
88
'compiled/collections/PaginatedCollection'
99
'compiled/collections/WrappedCollection'
1010
'compiled/util/natcompare'
11-
], ($, _, {Collection}, Section, Group, Outcome, PaginatedCollection, WrappedCollection, natcompare) ->
11+
'timezone'
12+
], ($, _, {Collection}, Section, Group, Outcome, PaginatedCollection, WrappedCollection, natcompare, tz) ->
1213
class GroupCollection extends PaginatedCollection
1314
@optionProperty 'course_id'
1415
model: Group
@@ -33,7 +34,7 @@ define [
3334
scoresFor: (outcome) ->
3435
@chain().map((result) ->
3536
if result.get('links').learning_outcome == outcome.id
36-
assessed_at: result.get('submitted_or_assessed_at')
37+
assessed_at: tz.parse(result.get('submitted_or_assessed_at'))
3738
score: result.get('score')
3839
).compact().value()
3940

app/coffeescripts/views/grade_summary/OutcomeLineGraphView.coffee

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ define [
22
'underscore'
33
'Backbone'
44
'vendor/d3.v3'
5+
'jst/outcomes/accessibleLineGraph'
56
'compiled/underscore-ext/sum'
6-
], (_, Backbone, d3) ->
7+
], (_, Backbone, d3, accessibleTemplate) ->
78
# Trend class based on formulae found here:
89
# http://classroom.synonym.com/calculate-trendline-2709.html
910
class Trend
@@ -82,19 +83,27 @@ define [
8283
.append("svg")
8384
.attr("width", @width() + @margin.left + @margin.right)
8485
.attr("height", @height + @margin.top + @margin.bottom)
86+
.attr("aria-hidden", true)
8587
.append("g")
8688
.attr("transform", "translate(#{@margin.left}, #{@margin.top})")
8789

8890
@_appendAxes()
8991
@_appendLines()
9092

93+
@$('.screenreader-only').append(accessibleTemplate(@toJSON()))
94+
9195
@
9296

97+
toJSON: ->
98+
current_user_name: ENV.current_user.display_name
99+
data: @data()
100+
outcome_name: @model.get('friendly_name')
101+
93102
# Data helpers
94103
data: ->
95104
@_data ?= _.chain(@model.get('scores'))
96105
.sortBy((score) =>
97-
@parseDate(score.assessed_at)
106+
score.assessed_at
98107
).last(@limit)
99108
.map((score, i) =>
100109
x: i
@@ -105,9 +114,6 @@ define [
105114
masteryPercentage: ->
106115
(@model.get('mastery_points') / @model.get('points_possible')) * 100
107116

108-
parseDate: (date) ->
109-
d3.time.format(@timeFormat).parse(date)
110-
111117
percentageFor: (score) ->
112118
((score / @model.get('points_possible')) * 100)
113119

@@ -181,8 +187,8 @@ define [
181187
@dateGuides = d3.svg.axis()
182188
.scale(@xTimeScale)
183189
.tickValues([
184-
@parseDate(_.first(@data()).date)
185-
@parseDate(_.last(@data()).date)
190+
_.first(@data()).date
191+
_.last(@data()).date
186192
])
187193
.tickFormat((d) -> d3.time.format("%m/%d")(d))
188194
@yAxis = d3.svg.axis()
@@ -219,8 +225,8 @@ define [
219225
@xTimeScale = d3.time.scale()
220226
.range([0, @xTimeScaleWidth()])
221227
.domain([
222-
@parseDate(_.first(@data()).date)
223-
@parseDate(_.last(@data()).date)
228+
_.first(@data()).date
229+
_.last(@data()).date
224230
])
225231
@y = d3.scale.linear()
226232
.range([@height, @margin.bottom])
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<table>
2+
<caption>
3+
{{#t}}
4+
The most recent scores for user {{ current_user_name }} and outcome {{ outcome_name }}.
5+
{{/t}}
6+
</caption>
7+
<tr>
8+
<th scope="col">Date</th>
9+
<th scope="col">Score</th>
10+
</tr>
11+
{{#each data}}
12+
<tr>
13+
<td scope="row">{{ tTimeToString (fudge date) "medium" }}</td>
14+
<td>{{ y }}</td>
15+
</tr>
16+
{{/each}}
17+
</table>

app/views/jst/outcomes/outcomePopover.handlebars

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<div class="outcome-details{{#if dialog}}-dialog{{/if}}">
2-
<div class="line-graph"></div>
2+
<div class="line-graph">
3+
<div class="screenreader-only"></div>
4+
</div>
35
<div class="head-content" tabindex="0">
46
{{#if path}}
57
<div class="title">{{path}}</div>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
define [
2+
'underscore'
3+
'compiled/models/grade_summary/Outcome'
4+
'compiled/views/grade_summary/OutcomeLineGraphView'
5+
'timezone'
6+
'helpers/fakeENV'
7+
], (_, Outcome, OutcomeLineGraphView, tz, fakeENV) ->
8+
9+
module 'OutcomeLineGraphViewSpec',
10+
setup: ->
11+
fakeENV.setup()
12+
ENV.current_user = {display_name: 'Student One'}
13+
14+
@outcomeLineGraphView = new OutcomeLineGraphView({
15+
el: $('<div class="line-graph"></div>')[0]
16+
model: new Outcome(
17+
friendly_name: 'Friendly Outcome Name'
18+
scores: []
19+
)
20+
})
21+
@scores = [{
22+
assessed_at: tz.parse('2015-02-01T12:30:40Z')
23+
score:5
24+
}, {
25+
assessed_at: tz.parse('2015-02-02T12:30:40Z')
26+
score:1
27+
}, {
28+
assessed_at: tz.parse('2015-02-03T12:30:40Z')
29+
score:2
30+
}]
31+
32+
teardown: ->
33+
fakeENV.teardown()
34+
35+
test 'render', ->
36+
ok @outcomeLineGraphView.render()
37+
ok _.isUndefined(@outcomeLineGraphView.svg),
38+
'should not render svg if no scores are present'
39+
40+
ok @outcomeLineGraphView.model.set(scores: @scores)
41+
ok @outcomeLineGraphView.render()
42+
ok !_.isUndefined(@outcomeLineGraphView.svg),
43+
'should render svg if scores are present'
44+
ok @outcomeLineGraphView.$('.screenreader-only'),
45+
'should render table of data for screen reader'

0 commit comments

Comments
 (0)