Skip to content

Commit 3177072

Browse files
authored
Toggle visibility of all student names (#1775)
* toggle visibility of all student names * Add toggle names button tests
1 parent 129fe10 commit 3177072

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

nbgrader/server_extensions/formgrader/static/js/gradebook_notebook_submissions.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ var SubmittedNotebookUI = Backbone.View.extend({
3737
showName: function () {
3838
this.$reveal.parent().find(".name-shown").show();
3939
this.$reveal.parent().find(".name-hidden").hide();
40+
updateToggleNamesButtonLabel();
4041
},
4142

4243
hideName: function () {
4344
this.$reveal.parent().find(".name-hidden").show();
4445
this.$reveal.parent().find(".name-shown").hide();
46+
updateToggleNamesButtonLabel();
4547
},
4648

4749
render: function () {
@@ -187,6 +189,33 @@ var loadSubmittedNotebooks = function () {
187189
});
188190
};
189191

192+
// at least one hidden name -> label="Show All Names"
193+
// no hidden name -> label="Hide All Names"
194+
let updateToggleNamesButtonLabel = function() {
195+
const button = document.getElementById("toggle_names");
196+
const icons = document.getElementsByClassName("glyphicon name-hidden");
197+
const icon_array = [...icons];
198+
if (icon_array.some(el => $(el).is(':visible'))){
199+
button.innerHTML = "Show All Names";
200+
} else{
201+
button.innerHTML = "Hide All Names";
202+
}
203+
};
204+
205+
// button to toggle all student names
206+
let toggleAllNames = function () {
207+
let icons;
208+
const button = document.getElementById("toggle_names");
209+
const names_hidden = (button.innerHTML === "Show All Names");
210+
if (names_hidden){
211+
icons = document.getElementsByClassName("glyphicon name-hidden");
212+
} else {
213+
icons = document.getElementsByClassName("glyphicon name-shown");
214+
}
215+
let icon_array = [...icons];
216+
icon_array.forEach(x => x.click());
217+
};
218+
190219
var models = undefined;
191220
var views = [];
192221
$(window).on('load', function () {

nbgrader/server_extensions/formgrader/templates/gradebook_notebook_submissions.tpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ var notebook_id = "{{ notebook_id }}";
1717
</ol>
1818
{%- endblock -%}
1919

20+
<!-- Button to toggle all student names -->
21+
{%- block messages -%}
22+
<button id="toggle_names" onclick="toggleAllNames()">Show All Names</button>
23+
{%- endblock -%}
24+
2025
{%- block table_header -%}
2126
<tr>
2227
<th></th>

nbgrader/tests/labextension_ui-tests/tests/test_formgrader.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,55 @@ test('Gradebook3 show hide names', async ({
510510

511511
});
512512

513+
/*
514+
Toggle name visibility button
515+
*/
516+
test('Gradebook toggle names button', async ({
517+
page,
518+
baseURL,
519+
tmpPath
520+
}) => {
521+
522+
test.skip(is_windows, 'This test does not work on Windows');
523+
524+
if (baseURL === undefined) throw new Error("BaseURL is undefined.");
525+
526+
// create environment
527+
await create_env(page, tmpPath, exchange_dir, cache_dir, is_windows);
528+
await add_courses(page, baseURL, tmpPath);
529+
await open_formgrader(page);
530+
531+
// get formgrader iframe
532+
const iframe = page.mainFrame().childFrames()[0];
533+
534+
// Change iframe URL to gradebook Problem Set 1
535+
await iframe.goto(`${baseURL}/formgrader/gradebook/Problem Set 1/Problem 1`);
536+
await check_formgrader_breadcrumbs(iframe, ["Manual Grading", "Problem Set 1", "Problem 1"]);
537+
538+
const button = iframe.locator("[id='toggle_names']").first()
539+
const hidden = iframe.locator("td .glyphicon.name-hidden").first();
540+
const shown = iframe.locator("td .glyphicon.name-shown").first();
541+
542+
// At the start, all names are hidden
543+
await expect(button).toHaveText("Show All Names", {useInnerText: true});
544+
await expect(hidden).toBeVisible();
545+
await expect(shown).toBeHidden();
546+
547+
// Clicking should make names shown
548+
await button.click();
549+
await expect(button).toHaveText("Hide All Names", {useInnerText: true});
550+
await expect(hidden).toBeHidden();
551+
await expect(shown).toBeVisible();
552+
553+
// If there is at least one hidden, button should default to showing all names
554+
await shown.click();
555+
await expect(button).toHaveText("Show All Names", {useInnerText: true});
556+
await button.click();
557+
await expect(hidden).toBeHidden();
558+
await expect(shown).toBeVisible();
559+
560+
});
561+
513562
/*
514563
* Load students and test students links
515564
*/

nbgrader/tests/nbextensions/test_formgrader.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,38 @@ def test_gradebook3_show_hide_names(browser, port, gradebook):
278278
assert hidden.is_displayed()
279279

280280

281+
@pytest.mark.nbextensions
282+
def test_gradebook_toggle_names_button(browser, port, gradebook):
283+
problem = gradebook.find_assignment("Problem Set 1").notebooks[0]
284+
utils._load_gradebook_page(browser, port, "gradebook/Problem Set 1/{}".format(problem.name))
285+
submissions = problem.submissions
286+
submissions.sort(key=lambda x: x.id)
287+
288+
button = browser.find_element(By.ID, "toggle_names")
289+
row1 = browser.find_element(By.CSS_SELECTOR, "tbody tr")
290+
col1 = row1.find_element(By.CSS_SELECTOR, "td")
291+
hidden = col1.find_element(By.CSS_SELECTOR, ".glyphicon.name-hidden")
292+
shown = col1.find_element(By.CSS_SELECTOR, ".glyphicon.name-shown")
293+
294+
# At the start, all names are hidden
295+
assert button.text == "Show All Names"
296+
assert hidden.is_displayed()
297+
assert not shown.is_displayed()
298+
299+
# Clicking should make names shown
300+
button.click()
301+
assert button.text == "Hide All Names"
302+
assert not hidden.is_displayed()
303+
assert shown.is_displayed()
304+
305+
# If there is at least one hidden, button should default to showing all names
306+
shown.click()
307+
assert button.text == "Show All Names"
308+
button.click()
309+
assert not hidden.is_displayed()
310+
assert shown.is_displayed()
311+
312+
281313
@pytest.mark.nbextensions
282314
def test_load_student1(browser, port, gradebook):
283315
# load the student view

0 commit comments

Comments
 (0)