Commit d7f69613 by Tyler Hallada Committed by Dennis Jen

Refactored filter.js for generic-list.

parent 25821f65
......@@ -20,7 +20,7 @@ define(function(require) {
},
initialize: function(options) {
this.options = options || {};
this.listenTo(this.options.collection, 'sync', this.onCourseListCollectionUpdated);
this.listenTo(this.options.collection, 'backgrid:refresh', this.onCourseListCollectionUpdated);
},
onBeforeShow: function() {
this.onCourseListCollectionUpdated(this.options.collection);
......
......@@ -17,10 +17,8 @@
<% if (filterKey === 'ignore_segments') { %>
<div id="<%- filterId %>">
<% _.each(filterValues, function (filterValue) { %>
<% if (filterValue.name === 'inactive') { %>
<input id="<%- filterValue.name %>" type="checkbox" value="<%- filterValue.name %>" <% if (hideInactive) { %> checked <% } %>>
<label for="<%- filterValue.name %>"> <%- selectDisplayName %> </label><br>
<% } %>
<input id="<%- filterValue.name %>" type="checkbox" value="<%- filterValue.name %>" <% if (filterValue.selected) { %> checked <% } %>>
<label for="<%- filterValue.name %>"> <%- selectDisplayName %> </label><br>
<% }); %>
</div>
<% } %>
......
......@@ -27,10 +27,10 @@ define(function(require) {
// It is assumed that there can never be a filter with an empty
// name, therefore it's safe to use the empty string as a
// property in this object. The API interprets this as "all
// learners, unfiltered".
// items, unfiltered".
catchAllFilterValue: '',
className: 'learners-filter',
className: 'list-filter',
template: _.template(filterTemplate),
......@@ -39,13 +39,11 @@ define(function(require) {
*
* @param options an options object which must include the following
* key/values:
* - collection (LearnersCollection): the learners collection to
* filter.
* - filterKey (string): the field to be filtered by on the learner
* collection.
* - collection: the collection to filter.
* - filterKey (string): the field to be filtered by on the collection.
* - filterValues (Object): the set of valid values that the
* filterKey can take on, represented as a mapping from
* filter values to the number of learners matching the applied
* filter values to the number of items matching the applied
* filter.
* - selectDisplayName (string): a *translated* string that will
* appear as the label for this filter.
......@@ -65,36 +63,37 @@ define(function(require) {
// 'displayName' is the user-facing representation of the filter
// which combines the filter with the number of users belonging to
// it.
var hideInactive = false,
filterValues,
var filterValues,
selectedFilterValue;
filterValues = _.chain(this.options.filterValues)
.pairs()
.map(function(filterPair) {
var name = filterPair[0],
numLearners = filterPair[1];
numResults = filterPair[1];
return {
name: name,
displayName: _.template(
// eslint-disable-next-line max-len
// Translators: 'name' here refers to the name of the filter, while 'numLearners' refers to the number of learners belonging to that filter.
gettext('<%= name %> (<%= numLearners %>)')
// Translators: 'name' here refers to the name of the filter, while 'numResults' refers to the number of items belonging to that filter.
gettext('<%= name %> (<%= numResults %>)')
)({
name: name,
numLearners: Utils.localizeNumber(numLearners, 0)
numLearners: Utils.localizeNumber(numResults, 0)
})
};
})
.sortBy('name')
.value();
if (filterValues.length) {
if (filterValues.length && this.options.filterInput === 'select') {
filterValues.unshift({
name: this.catchAllFilterValue,
// Translators: "All" refers to viewing all the learners in a course.
displayName: gettext('All')
});
// FIXME: The following code isn't working correctly. getActiveFilterFields seems to return an object,
// not an array.
// Assumes that you can only filter by one filterKey at a time.
selectedFilterValue = _.chain(filterValues)
.pluck('name')
......@@ -103,31 +102,31 @@ define(function(require) {
.value() || this.catchAllFilterValue;
_.findWhere(filterValues, {name: selectedFilterValue}).selected = true;
}
if (this.options.filterKey === 'ignore_segments') {
// Translators: inactive meaning that these learners have not interacted with the course recently.
this.options.selectDisplayName = gettext('Hide Inactive Learners');
}
if ('ignore_segments' in this.options.collection.getActiveFilterFields()) {
hideInactive = true;
}
return {
filterKey: this.options.filterKey,
filterValues: filterValues,
hideInactive: hideInactive,
selectDisplayName: this.options.selectDisplayName
};
},
onCheckboxFilter: function(event) {
if ($(event.currentTarget).find('input:checkbox:checked').length) {
this.collection.setFilterField('ignore_segments', 'inactive');
var $inputs = $(event.currentTarget).find('input:checkbox:checked'),
filterKey = $(event.currentTarget).attr('id').slice(7), // chop off "filter-" prefix
appliedFilters = [],
filterValue = '';
if ($inputs.length) {
_.each($inputs, _.bind(function(input) {
appliedFilters.push($(input).attr('id'));
}, this));
filterValue = appliedFilters.join(',');
this.collection.setFilterField(filterKey, filterValue);
} else {
this.collection.unsetFilterField('ignore_segments');
this.collection.unsetFilterField(filterKey);
}
this.collection.refresh();
$('#app-focusable').focus();
this.options.trackingModel.trigger('segment:track', 'edx.bi.roster.filtered', {
category: 'inactive'
this.options.trackingModel.trigger('segment:track', 'edx.bi.list.filtered', {
category: filterValue
});
},
......
/**
* Displays either a paginated table of learners or a message that there are
* no learners to display.
*/
define(function(require) {
'use strict';
var _ = require('underscore'),
Marionette = require('marionette'),
AlertView = require('generic-view/common/views/alert-view'),
LearnerTableView = require('learners/roster/views/table'),
LearnerResultsView;
LearnerResultsView = Marionette.LayoutView.extend({
template: _.template('<div class="roster-main"></div>'),
regions: {
main: '.roster-main'
},
initialize: function(options) {
this.options = options || {};
this.listenTo(this.options.collection, 'sync', this.onLearnerCollectionUpdated);
},
onBeforeShow: function() {
this.onLearnerCollectionUpdated(this.options.collection);
},
onLearnerCollectionUpdated: function(collection) {
if (collection.length && this.options.hasData) {
// Don't re-render the learner table view if one already exists.
if (!(this.getRegion('main').currentView instanceof LearnerTableView)) {
this.showChildView('main', new LearnerTableView({
collection: collection,
courseMetadata: this.options.courseMetadata,
trackingModel: this.options.trackingModel
}));
}
} else {
this.showChildView('main', this.createAlertView(collection));
}
},
createAlertView: function(collection) {
var hasSearch = collection.hasActiveSearch(),
hasActiveFilter = !_.isEmpty(collection.getActiveFilterFields()),
suggestions = [],
noLearnersMessage,
detailedMessage;
if (hasSearch || hasActiveFilter) {
noLearnersMessage = gettext('No learners matched your criteria.');
if (hasSearch) {
suggestions.push(gettext('Try a different search.'));
}
if (hasActiveFilter) {
suggestions.push(gettext('Try clearing the filters.'));
}
} else {
noLearnersMessage = gettext('No learner data is currently available for your course.');
// eslint-disable-next-line max-len
detailedMessage = gettext('No learners are enrolled, or course activity data has not yet been processed. Data is updated every day, so check back regularly for up-to-date metrics.');
}
return new AlertView({
alertType: 'info',
title: noLearnersMessage,
body: detailedMessage,
suggestions: suggestions
});
}
});
return LearnerResultsView;
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment