Commit 20cd73dc by Vedran Karacic

Load courses asynchronously on dynamic coupon preview.

parent 47d7812b
...@@ -41,21 +41,30 @@ class CatalogViewSet(NestedViewSetMixin, ReadOnlyModelViewSet): ...@@ -41,21 +41,30 @@ class CatalogViewSet(NestedViewSetMixin, ReadOnlyModelViewSet):
""" """
query = request.GET.get('query') query = request.GET.get('query')
seat_types = request.GET.get('seat_types') seat_types = request.GET.get('seat_types')
offset = request.GET.get('offset')
limit = request.GET.get('limit', DEFAULT_CATALOG_PAGE_SIZE)
if query and seat_types: if query and seat_types:
seat_types = seat_types.split(',') seat_types = seat_types.split(',')
try: try:
results = get_range_catalog_query_results( response = get_range_catalog_query_results(
limit=DEFAULT_CATALOG_PAGE_SIZE, limit=limit,
query=query, query=query,
site=request.site site=request.site,
)['results'] offset=offset
)
results = response['results']
course_ids = [result['key'] for result in results] course_ids = [result['key'] for result in results]
courses = serializers.CourseSerializer( courses = serializers.CourseSerializer(
Course.objects.filter(id__in=course_ids), Course.objects.filter(id__in=course_ids),
many=True, many=True,
context={'request': request} context={'request': request}
).data ).data
return Response(data=[course for course in courses if course['type'] in seat_types]) data = {
'next': response['next'],
'courses': [course for course in courses if course['type'] in seat_types]
}
return Response(data=data)
except (ConnectionError, SlumberBaseException, Timeout): except (ConnectionError, SlumberBaseException, Timeout):
logger.error('Unable to connect to Course Catalog service.') logger.error('Unable to connect to Course Catalog service.')
return Response(status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_400_BAD_REQUEST)
......
...@@ -46,37 +46,18 @@ define([ ...@@ -46,37 +46,18 @@ define([
}); });
}); });
it('should call Course Catalog API if previewCatalog was called', function () { it('should call Course Catalog API if previewCatalog was called and create a datatable', function () {
var args, var args,
calls, calls,
e = $.Event('click'); e = $.Event('click');
spyOn(e, 'preventDefault'); spyOn(e, 'preventDefault');
spyOn(Backbone, 'ajax'); spyOn(Backbone, 'ajax');
spyOn($.prototype, 'DataTable').and.callThrough();
view.previewCatalog(e); view.previewCatalog(e);
expect(e.preventDefault).toHaveBeenCalled(); expect(e.preventDefault).toHaveBeenCalled();
expect(Backbone.ajax).toHaveBeenCalled(); expect(Backbone.ajax).toHaveBeenCalled();
calls = Backbone.ajax.calls;
args = calls.argsFor(calls.count() - 1)[0];
expect(args.type).toEqual('GET');
expect(args.url).toEqual(window.location.origin + '/api/v2/catalogs/preview/');
expect(args.data).toEqual({query: view.query, seat_types: view.seat_types.join()});
expect(args.success).toEqual(view.onSuccess);
});
it('should fill datatable on successful AJAX call to Course Catalog API', function () {
var API_data = [{
key: 'a/b/c'
}, {
key: 'd/e/f'
}],
args;
spyOn($.prototype, 'DataTable');
view.onSuccess(API_data);
expect($.prototype.DataTable).toHaveBeenCalled(); expect($.prototype.DataTable).toHaveBeenCalled();
args = $.prototype.DataTable.calls.argsFor(0)[0]; args = $.prototype.DataTable.calls.argsFor(0)[0];
...@@ -87,10 +68,52 @@ define([ ...@@ -87,10 +68,52 @@ define([
expect(args.ordering).toBeFalsy(); expect(args.ordering).toBeFalsy();
expect(args.searching).toBeFalsy(); expect(args.searching).toBeFalsy();
expect(args.columns).toEqual([ expect(args.columns).toEqual([
{title: 'Course ID', data: 'id'}, {
{title: 'Course name', data: 'name'}, title: 'Course ID', data: 'id',
{title: 'Seat type', data: 'type'} sTitle: 'Course ID', mData: 'id'
},
{
title: 'Course name', data: 'name',
sTitle: 'Course name', mData: 'name',
},
{
title: 'Seat type', data: 'type',
sTitle: 'Seat type', mData: 'type',
}
]); ]);
calls = Backbone.ajax.calls;
args = calls.argsFor(calls.count() - 1)[0];
expect(args.type).toEqual('GET');
expect(args.url).toEqual(window.location.origin + '/api/v2/catalogs/preview/');
expect(args.data).toEqual(
{query: view.query, seat_types: view.seat_types.join(), limit: 10, offset: 0}
);
expect(args.success).toEqual(view.onSuccess);
});
it('should fill datatable on successful AJAX call to Course Catalog API', function () {
var API_data = {
'next': 'test.link',
'courses': [{
id: 'a/b/c',
name: 'Test course 1',
type: 'verified'
}, {
id: 'd/e/f',
name: 'Test course 2',
type: 'professional'
}]
};
view.previewCatalog($.Event('click'));
this.table = view.$('#coursesTable').DataTable();
_.bind(view.onSuccess, this);
spyOn(window, 'setTimeout');
view.onSuccess(API_data);
expect(window.setTimeout).toHaveBeenCalled();
expect(this.table.row(0).data()).toEqual(view.getRowData(API_data.courses[0]));
expect(this.table.row(1).data()).toEqual(view.getRowData(API_data.courses[1]));
}); });
it('should call stopEventPropagation when disabled or active button pressed', function () { it('should call stopEventPropagation when disabled or active button pressed', function () {
......
...@@ -38,44 +38,62 @@ define(['jquery', ...@@ -38,44 +38,62 @@ define(['jquery',
}, },
previewCatalog: function (event) { previewCatalog: function (event) {
this.limit = 10;
this.offset = 0;
event.preventDefault(); event.preventDefault();
if (!$.fn.dataTable.isDataTable('#coursesTable') ||
(this.used_query !== this.query || this.used_seat_types !== this.seat_types)
) {
this.table = this.$('#coursesTable').DataTable({
autoWidth: false,
destroy: true,
info: true,
paging: true,
ordering: false,
searching: false,
columns: [
{
title: gettext('Course ID'),
data: 'id'
},
{
title: gettext('Course name'),
data: 'name'
},
{
title: gettext('Seat type'),
data: 'type'
}
]
}, this).clear().draw();
this.used_query = this.query;
this.used_seat_types = this.seat_types;
this.fetchCourseData();
}
},
fetchCourseData: function() {
Backbone.ajax({ Backbone.ajax({
context: this, context: this,
type: 'GET', type: 'GET',
url: window.location.origin + '/api/v2/catalogs/preview/', url: window.location.origin + '/api/v2/catalogs/preview/',
data: { data: {
query : this.query, query : this.query,
seat_types: this.seat_types.join() seat_types: this.seat_types.join(),
limit: this.limit,
offset: this.offset
}, },
success: this.onSuccess success: this.onSuccess
}); });
}, },
onSuccess: function(data) { onSuccess: function(data) {
this.$el.find('#coursesTable').DataTable({ var tableData = data.courses.map(this.getRowData, this);
autoWidth: false, this.table.rows.add(tableData).draw();
destroy: true, if (data.next) {
info: true, this.offset += this.limit;
paging: true, setTimeout(_.bind(this.fetchCourseData, this), 500);
ordering: false, }
searching: false,
columns: [
{
title: gettext('Course ID'),
data: 'id'
},
{
title: gettext('Course name'),
data: 'name'
},
{
title: gettext('Seat type'),
data: 'type'
}
],
data: data.map(this.getRowData, this)
}, this);
}, },
render: function () { render: function () {
......
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