Skip to content

Commit

Permalink
SAK-39978: Develop an empty state for Gradebook to better orientate a…
Browse files Browse the repository at this point in the history
…nd guide user (sakaiproject#5632)
  • Loading branch information
plukasew authored and bjones86 committed Jun 19, 2018
1 parent 486115c commit f1f2179
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ permissionspage.update.dupes=Note: One or more duplicate permissions were detect


no-assignments.label = There are no Gradebook items
no-students.label = There are no students with Gradebook items
no-students.label = There are no students to display

gradebookpage.uncategorised = Uncategorized

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,89 +5,100 @@

<wicket:extend>
<form wicket:id="form" id="gradebookSpreadsheet">
<div wicket:id="noAssignments" class="messageInformation"><wicket:message key="no-assignments.label" /></div>
<div wicket:id="noStudents" class="messageInformation"><wicket:message key="no-students.label" /></div>
<div id="gbConnectionTimeoutFeedback" class="messageWarning" style="display:none;">
<wicket:message key="feedback.connectiontimeout" />
</div>
<div id="gbReorderColumnsFailed" class="messageWarning" style="display:none;">
<wicket:message key="feedback.reordercolumnsfailed" />
</div>

<div class="row">
<div class="col-sm-12">
<div class="col-sm-6">
<button wicket:id="addGradeItem" class="button_color gb-add-gradebook-item-button">
<div wicket:id="addOrEditGradeItemWindow" />
<div wicket:id="studentGradeSummaryWindow" />
<div wicket:id="updateUngradedItemsWindow" />
<div wicket:id="gradeLogWindow" />
<div wicket:id="gradeCommentWindow" />
<div wicket:id="deleteItemWindow" />
<div wicket:id="gradeStatisticsWindow" />
<div wicket:id="updateCourseGradeDisplayWindow" />
<div wicket:id="sortGradeItemsWindow" />
<div wicket:id="courseGradeStatisticsWindow" />

<div wicket:id="gradeTableArea">
<div wicket:id="noAssignments" class="gb-noGbItems">
<i class="fa fa-fw fa-table" aria-hidden="true"></i>
<wicket:message key="no-assignments.label" />
<div class="act">
<button wicket:id="addGradeItem2" class="active gb-add-gradebook-item-button">
<wicket:message key="button.addgradeitem" />
</button>
</div>
</div>

<div wicket:id="liveGradingFeedback" class="gb-live-feedback"></div>
<div class="row gradesToolbar1">
<div class="col-sm-12">
<div class="col-sm-6">
<button wicket:id="addGradeItem" class="button_color gb-add-gradebook-item-button">
<wicket:message key="button.addgradeitem" />
</button>
<div wicket:id="liveGradingFeedback" class="gb-live-feedback"></div>
</div>
<div class="col-sm-6 text-right">
<wicket:enclosure>
<label for="filterByGroup" class="sr-only"><wicket:message key="filter.groups" /></label>
<select id="filterByGroup" wicket:id="groupFilter">
<option value="1">Section 1</option>
<option value="2">Section 2</option>
</select>
</wicket:enclosure>
<a wicket:id="captionToggle" href="javascript:void(0);" id="captionToggle" aria-popup="true" aria-controls="gradeTableCaption">
<span class="sr-only">
<wicket:message key="label.toolbar.togglehelp"/>
</span>
</a>
</div>
</div>
<div class="col-sm-6 text-right">
</div>

<div wicket:id="toolbar" id="gradebookGradesToolbar" class="btn-toolbar gradesToolbar2">
<ul class="gb-toolbar-left">
<wicket:enclosure>
<label for="filterByGroup" class="sr-only"><wicket:message key="filter.groups" /></label>
<select id="filterByGroup" wicket:id="groupFilter">
<option value="1">Section 1</option>
<option value="2">Section 2</option>
</select>
<li>
<div class="gb-student-filter">
<label for="studentFilterInput" class="sr-only"><wicket:message key="filter.students"/></label>
<input type="text" id="studentFilterInput" class="form-control" aria-controls="gradeTable" wicket:id="studentFilter" wicket:message="placeholder:filter.students" accesskey="f">
<a class="gb-student-filter-clear-button" wicket:message="title:filter.studentsclear" href="javascript:void(0)">
<i class="fa fa-times-circle" aria-hidden="true"></i>
</a>
</div>
</li>
</wicket:enclosure>
<a wicket:id="captionToggle" href="javascript:void(0);" id="captionToggle" aria-popup="true" aria-controls="gradeTableCaption">
<span class="sr-only">
<wicket:message key="label.toolbar.togglehelp"/>
</span>
</a>
</div>
<wicket:enclosure>
<li><span wicket:id="groupFilterOnlyOne" class="gb-group-title" role="status">Section 001</span></li>
</wicket:enclosure>
<li class="gb-student-summary"><!-- Populated by JavaScript --></li>
</ul>
<ul wicket:id="gbToolbarColumnTools" class="gb-toolbar-right">
<li class="gb-grade-item-summary"><!-- Populated by JavaScript --></li>
<li>
<button wicket:id="toggleGradeItemsToolbarItem" id="toggleGradeItemsToolbarItem" class="button" aria-popup="true" aria-controls="gradeItemsTogglePanel"><wicket:message key="label.toolbar.toggleitems"/></button>
</li>
<li>
<button wicket:id="sortGradeItemsToolbarItem" id="sortGradeItemsToolbarItem" class="button" aria-popup="true"><wicket:message key="label.toolbar.sortgradeitems"/></button>
</li>
<wicket:enclosure>
<li>
<button wicket:id="toggleCategoriesToolbarItem" id="toggleCategoriesToolbarItem" class="button" aria-controls="gradeTable"><wicket:message key="label.toolbar.togglecategories"/></button>
</li>
</wicket:enclosure>
</ul>
</div>
</div>

<div wicket:id="addOrEditGradeItemWindow" />
<div wicket:id="studentGradeSummaryWindow" />
<div wicket:id="updateUngradedItemsWindow" />
<div wicket:id="gradeLogWindow" />
<div wicket:id="gradeCommentWindow" />
<div wicket:id="deleteItemWindow" />
<div wicket:id="gradeStatisticsWindow" />
<div wicket:id="updateCourseGradeDisplayWindow" />
<div wicket:id="sortGradeItemsWindow" />
<div wicket:id="courseGradeStatisticsWindow" />

<div wicket:id="toolbar" id="gradebookGradesToolbar" class="btn-toolbar">
<ul class="gb-toolbar-left">
<wicket:enclosure>
<li>
<div class="gb-student-filter">
<label for="studentFilterInput" class="sr-only"><wicket:message key="filter.students"/></label>
<input type="text" id="studentFilterInput" class="form-control" aria-controls="gradeTable" wicket:id="studentFilter" wicket:message="placeholder:filter.students" accesskey="f">
<a class="gb-student-filter-clear-button" wicket:message="title:filter.studentsclear" href="javascript:void(0)">
<i class="fa fa-times-circle" aria-hidden="true"></i>
</a>
</div>
</li>
</wicket:enclosure>
<wicket:enclosure>
<li><span wicket:id="groupFilterOnlyOne" class="gb-group-title" role="status">Section 001</span></li>
</wicket:enclosure>
<li class="gb-student-summary"><!-- Populated by JavaScript --></li>
</ul>
<ul class="gb-toolbar-right">
<li class="gb-grade-item-summary"><!-- Populated by JavaScript --></li>
<li>
<button wicket:id="toggleGradeItemsToolbarItem" id="toggleGradeItemsToolbarItem" class="button" aria-popup="true" aria-controls="gradeItemsTogglePanel"><wicket:message key="label.toolbar.toggleitems"/></button>
</li>
<li>
<button wicket:id="sortGradeItemsToolbarItem" id="sortGradeItemsToolbarItem" class="button" aria-popup="true"><wicket:message key="label.toolbar.sortgradeitems"/></button>
</li>
<wicket:enclosure>
<li>
<button wicket:id="toggleCategoriesToolbarItem" id="toggleCategoriesToolbarItem" class="button" aria-controls="gradeTable"><wicket:message key="label.toolbar.togglecategories"/></button>
</li>
</wicket:enclosure>
</ul>
<div class="gradeTableOuterWrapper">
<div wicket:id="gradeTable" />
<div wicket:id="noStudents" class="gb-noStudents"><wicket:message key="no-students.label" /></div>
</div>
</div>

<!-- Here we go... -->
<div wicket:id="gradeTable" />

</form>

<div wicket:id="gradeItemsTogglePanel" id="gradeItemsTogglePanel" style="display: none;"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public class GradebookPage extends BasePage {
GbModalWindow courseGradeStatisticsWindow;

Label liveGradingFeedback;
boolean hasAssignmentsAndGrades;
boolean hasGradebookItems, hasStudents;
private static final AttributeModifier DISPLAY_NONE = new AttributeModifier("style", "display: none");

Form<Void> form;
Expand All @@ -115,6 +115,8 @@ public class GradebookPage extends BasePage {
boolean showGroupFilter = true;
private GbGradeTable gradeTable;

private final WebMarkupContainer tableArea;

@SuppressWarnings({ "rawtypes", "unchecked", "serial" })
public GradebookPage() {
disableLink(this.gradebookPageLink);
Expand Down Expand Up @@ -195,25 +197,6 @@ public GradebookPage() {
this.courseGradeStatisticsWindow.setPositionAtTop(true);
this.form.add(this.courseGradeStatisticsWindow);

final GbAjaxButton addGradeItem = new GbAjaxButton("addGradeItem") {
@Override
public void onSubmit(final AjaxRequestTarget target, final Form form) {
final GbModalWindow window = getAddOrEditGradeItemWindow();
window.setTitle(getString("heading.addgradeitem"));
window.setComponentToReturnFocusTo(this);
window.setContent(new AddOrEditGradeItemPanel(window.getContentId(), window, null));
window.show(target);
}

@Override
public boolean isVisible() {
return (businessService.isUserAbleToEditAssessments());
}
};
addGradeItem.setDefaultFormProcessing(false);
addGradeItem.setOutputMarkupId(true);
this.form.add(addGradeItem);

// first get any settings data from the session
final GradebookUiSettings settings = getUiSettings();

Expand All @@ -227,28 +210,52 @@ public boolean isVisible() {
final List<Assignment> assignments = this.businessService.getGradebookAssignments(sortBy);
final List<String> students = this.businessService.getGradeableUsers();

this.hasAssignmentsAndGrades = !assignments.isEmpty() && !students.isEmpty();

hasGradebookItems = !assignments.isEmpty();
hasStudents = !students.isEmpty();
// categories enabled?
final boolean categoriesEnabled = this.businessService.categoriesAreEnabled();

// grading type?
final GradingType gradingType = GradingType.valueOf(gradebook.getGrade_type());

tableArea = new WebMarkupContainer("gradeTableArea");
if (!hasGradebookItems) {
tableArea.add(AttributeAppender.append("class", "gradeTableArea"));
}
form.add(tableArea);

final GbAddButton addGradeItem = new GbAddButton("addGradeItem");
addGradeItem.setDefaultFormProcessing(false);
addGradeItem.setOutputMarkupId(true);
tableArea.add(addGradeItem);

final WebMarkupContainer noAssignments = new WebMarkupContainer("noAssignments");
noAssignments.setVisible(assignments.isEmpty());
this.form.add(noAssignments);
tableArea.add(noAssignments);
final GbAddButton addGradeItem2 = new GbAddButton("addGradeItem2") {
@Override
public boolean isVisible() {
return GradebookPage.this.role == GbRole.INSTRUCTOR;
}
};
addGradeItem2.setDefaultFormProcessing(false);
addGradeItem2.setOutputMarkupId(true);
noAssignments.add(addGradeItem2);

final WebMarkupContainer noStudents = new WebMarkupContainer("noStudents");
noStudents.setVisible(students.isEmpty());
this.form.add(noStudents);
tableArea.add(noStudents);

// Populate the toolbar
final WebMarkupContainer toolbar = new WebMarkupContainer("toolbar");
this.form.add(toolbar);
tableArea.add(toolbar);

final WebMarkupContainer toolbarColumnTools = new WebMarkupContainer("gbToolbarColumnTools");
toolbarColumnTools.setVisible(hasGradebookItems);
toolbar.add(toolbarColumnTools);

final WebMarkupContainer toggleGradeItemsToolbarItem = new WebMarkupContainer("toggleGradeItemsToolbarItem");
toolbar.add(toggleGradeItemsToolbarItem);
toolbarColumnTools.add(toggleGradeItemsToolbarItem);

this.gradeTable = new GbGradeTable("gradeTable",
new LoadableDetachableModel() {
Expand Down Expand Up @@ -276,7 +283,7 @@ public GbGradeTableData load() {
this.gradeTable.addEventListener("viewCourseGradeStatistics", new ViewCourseGradeStatisticsAction());


this.form.add(this.gradeTable);
tableArea.add(this.gradeTable);

final Button toggleCategoriesToolbarItem = new Button("toggleCategoriesToolbarItem") {
@Override
Expand All @@ -302,7 +309,7 @@ public boolean isVisible() {
return categoriesEnabled;
}
};
toolbar.add(toggleCategoriesToolbarItem);
toolbarColumnTools.add(toggleCategoriesToolbarItem);

final GbAjaxLink sortGradeItemsToolbarItem = new GbAjaxLink("sortGradeItemsToolbarItem") {
@Override
Expand All @@ -324,7 +331,7 @@ public boolean isVisible() {
return (businessService.isUserAbleToEditAssessments());
}
};
toolbar.add(sortGradeItemsToolbarItem);
toolbarColumnTools.add(sortGradeItemsToolbarItem);

// section and group dropdown
final List<GbGroup> groups = this.businessService.getSiteSectionsAndGroups();
Expand Down Expand Up @@ -405,15 +412,13 @@ protected void onUpdate(final AjaxRequestTarget target) {
groupFilter.setNullValid(false);

// if only one item, hide the dropdown
if (groups.size() == 1 || !this.hasAssignmentsAndGrades) {
groupFilter.setVisible(false);
}
groupFilter.setVisible(groups.size() > 1 && hasStudents);

final WebMarkupContainer studentFilter = new WebMarkupContainer("studentFilter");
studentFilter.setVisible(this.hasAssignmentsAndGrades);
studentFilter.setVisible(hasStudents);
toolbar.add(studentFilter);

this.form.add(groupFilter);
tableArea.add(groupFilter);

final Map<String, Object> togglePanelModel = new HashMap<>();
togglePanelModel.put("assignments", this.businessService.getGradebookAssignments(sortBy));
Expand All @@ -424,17 +429,9 @@ protected void onUpdate(final AjaxRequestTarget target) {
new ToggleGradeItemsToolbarPanel("gradeItemsTogglePanel", Model.ofMap(togglePanelModel));
add(gradeItemsTogglePanel);

this.form.add(new WebMarkupContainer("captionToggle").setVisible(this.hasAssignmentsAndGrades));

//
// hide/show components
//
tableArea.add(new WebMarkupContainer("captionToggle").setVisible(hasStudents));

// Only show the toolbar if there are students and grade items
toolbar.setVisible(!assignments.isEmpty());

// Show the table if there are grade items
this.gradeTable.setVisible(!assignments.isEmpty());
toolbar.setVisible(hasStudents || hasGradebookItems);

stopwatch.time("Gradebook page done", stopwatch.getTime());
}
Expand Down Expand Up @@ -560,15 +557,15 @@ public void onBeforeRender() {
// add simple feedback nofication to sit above the table
// which is reset every time the page renders
this.liveGradingFeedback = new Label("liveGradingFeedback", getString("feedback.saved"));
this.liveGradingFeedback.setVisible(this.hasAssignmentsAndGrades);
this.liveGradingFeedback.setVisible(hasGradebookItems && hasStudents);
this.liveGradingFeedback.setOutputMarkupId(true);
this.liveGradingFeedback.add(DISPLAY_NONE);

// add the 'saving...' message to the DOM as the JavaScript will
// need to be the one that displays this message (Wicket will handle
// the 'saved' and 'error' messages when a grade is changed
this.liveGradingFeedback.add(new AttributeModifier("data-saving-message", getString("feedback.saving")));
this.form.addOrReplace(this.liveGradingFeedback);
tableArea.addOrReplace(this.liveGradingFeedback);
}

public Component updateLiveGradingMessage(final String message) {
Expand All @@ -578,4 +575,29 @@ public Component updateLiveGradingMessage(final String message) {
}
return this.liveGradingFeedback;
}

private class GbAddButton extends GbAjaxButton {

public GbAddButton(String id) {
super(id);
}

public GbAddButton(String id, Form<?> form) {
super(id, form);
}

@Override
public void onSubmit(final AjaxRequestTarget target, final Form form) {
final GbModalWindow window = getAddOrEditGradeItemWindow();
window.setTitle(getString("heading.addgradeitem"));
window.setComponentToReturnFocusTo(this);
window.setContent(new AddOrEditGradeItemPanel(window.getContentId(), window, null));
window.show(target);
}

@Override
public boolean isVisible() {
return GradebookPage.this.role == GbRole.INSTRUCTOR && hasGradebookItems;
}
}
}
Loading

0 comments on commit f1f2179

Please sign in to comment.