-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1113 from jhamrick/course-list
Add a course list extension that shows all courses an instructor can manage
- Loading branch information
Showing
12 changed files
with
727 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#courses .panel-group .panel { | ||
margin-top: 3px; | ||
margin-bottom: 1em; | ||
} | ||
|
||
#courses .panel-group .panel .panel-heading { | ||
background-color: #eee; | ||
padding-top: 4px; | ||
padding-bottom: 4px; | ||
padding-left: 7px; | ||
padding-right: 7px; | ||
line-height: 22px; | ||
} | ||
|
||
#courses .panel-group .panel .panel-heading a:focus, a:hover { | ||
text-decoration: none; | ||
} | ||
|
||
#courses .panel-group .panel .panel-body { | ||
padding: 0; | ||
} | ||
|
||
#courses .panel-group .panel .panel-body .list_container { | ||
margin-top: 0px; | ||
margin-bottom: 0px; | ||
border: 0px; | ||
border-radius: 0px; | ||
} | ||
|
||
#courses .panel-group .panel .panel-body .list_container .list_item { | ||
border-bottom: 1px solid #ddd; | ||
} | ||
|
||
#courses .panel-group .panel .panel-body .list_container .list_item:last-child { | ||
border-bottom: 0px; | ||
} | ||
|
||
#courses .list_item { | ||
padding-top: 4px; | ||
padding-bottom: 4px; | ||
padding-left: 7px; | ||
padding-right: 7px; | ||
line-height: 22px; | ||
} | ||
|
||
#courses .list_item > div { | ||
padding-top: 0; | ||
padding-bottom: 0; | ||
padding-left: 0; | ||
padding-right: 0; | ||
} | ||
|
||
#courses .list_placeholder { | ||
display: none; | ||
} | ||
|
||
#courses .list_placeholder, #courses .list_loading, #courses .list_error { | ||
font-weight: bold; | ||
padding-top: 4px; | ||
padding-bottom: 4px; | ||
padding-left: 7px; | ||
padding-right: 7px; | ||
} | ||
|
||
#courses .list_error, #courses .version_error { | ||
display: none; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright (c) Jupyter Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||
|
||
define([ | ||
'base/js/namespace', | ||
'jquery', | ||
'base/js/utils', | ||
'base/js/dialog', | ||
], function(Jupyter, $, utils, dialog) { | ||
"use strict"; | ||
|
||
var ajax = utils.ajax || $.ajax; | ||
// Notebook v4.3.1 enabled xsrf so use notebooks ajax that includes the | ||
// xsrf token in the header data | ||
|
||
var CourseList = function (course_list_selector, refresh_selector, options) { | ||
this.course_list_selector = course_list_selector; | ||
this.refresh_selector = refresh_selector; | ||
|
||
this.course_list_element = $(course_list_selector); | ||
this.refresh_element = $(refresh_selector); | ||
|
||
this.current_course = undefined; | ||
this.bind_events() | ||
|
||
options = options || {}; | ||
this.options = options; | ||
this.base_url = options.base_url || utils.get_body_data("baseUrl"); | ||
|
||
this.data = undefined; | ||
}; | ||
|
||
CourseList.prototype.bind_events = function () { | ||
var that = this; | ||
this.refresh_element.click(function () { | ||
that.load_list(); | ||
}); | ||
}; | ||
|
||
|
||
CourseList.prototype.clear_list = function (loading) { | ||
this.course_list_element.children('.list_item').remove(); | ||
if (loading) { | ||
// show loading | ||
this.course_list_element.children('.list_loading').show(); | ||
// hide placeholders and errors | ||
this.course_list_element.children('.list_placeholder').hide(); | ||
this.course_list_element.children('.list_error').hide(); | ||
|
||
} else { | ||
// show placeholders | ||
this.course_list_element.children('.list_placeholder').show(); | ||
// hide loading and errors | ||
this.course_list_element.children('.list_loading').hide(); | ||
this.course_list_element.children('.list_error').hide(); | ||
} | ||
}; | ||
|
||
CourseList.prototype.show_error = function (error) { | ||
this.course_list_element.children('.list_item').remove(); | ||
// show errors | ||
this.course_list_element.children('.list_error').show(); | ||
this.course_list_element.children('.list_error').text(error); | ||
// hide loading and placeholding | ||
this.course_list_element.children('.list_loading').hide(); | ||
this.course_list_element.children('.list_placeholder').hide(); | ||
}; | ||
|
||
CourseList.prototype.load_list = function () { | ||
this.clear_list(true); | ||
|
||
var settings = { | ||
processData : false, | ||
cache : false, | ||
type : "GET", | ||
dataType : "json", | ||
success : $.proxy(this.handle_load_list, this), | ||
error : utils.log_ajax_error, | ||
}; | ||
var url = utils.url_path_join(this.base_url, 'formgraders'); | ||
ajax(url, settings); | ||
}; | ||
|
||
CourseList.prototype.handle_load_list = function (data, status, xhr) { | ||
if (data.success) { | ||
this.load_list_success(data.value); | ||
} else { | ||
this.show_error(data.value); | ||
} | ||
}; | ||
|
||
CourseList.prototype.load_list_success = function (data) { | ||
this.clear_list(); | ||
var len = data.length; | ||
for (var i=0; i<len; i++) { | ||
var element = $('<div/>'); | ||
var item = new Course(element, data[i], this.course_list_selector, $.proxy(this.handle_load_list, this), this.options); | ||
this.course_list_element.append(element); | ||
this.course_list_element.children('.list_placeholder').hide() | ||
} | ||
|
||
if (this.callback) { | ||
this.callback(); | ||
this.callback = undefined; | ||
} | ||
}; | ||
|
||
var Course = function (element, data, parent, on_refresh, options) { | ||
this.element = $(element); | ||
this.course_id = data['course_id']; | ||
this.formgrader_kind = data['kind']; | ||
this.url = data['url']; | ||
this.parent = parent; | ||
this.on_refresh = on_refresh; | ||
this.options = options; | ||
this.style(); | ||
this.make_row(); | ||
}; | ||
|
||
Course.prototype.style = function () { | ||
this.element.addClass('list_item').addClass("row"); | ||
}; | ||
|
||
Course.prototype.make_row = function () { | ||
var row = $('<div/>').addClass('col-md-12'); | ||
var container = $('<span/>').addClass('item_name col-sm-2').append( | ||
$('<a/>') | ||
.attr('href', this.url) | ||
.attr('target', '_blank') | ||
.text(this.course_id)); | ||
row.append(container); | ||
row.append($('<span/>').addClass('item_course col-sm-2').text(this.formgrader_kind)); | ||
this.element.empty().append(row); | ||
}; | ||
|
||
return { | ||
'CourseList': CourseList, | ||
}; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
define([ | ||
'base/js/namespace', | ||
'jquery', | ||
'base/js/utils', | ||
'./course_list' | ||
], function(Jupyter, $, utils, CourseList) { | ||
"use strict"; | ||
|
||
var nbgrader_version = "0.6.0.dev"; | ||
|
||
var ajax = utils.ajax || $.ajax; | ||
// Notebook v4.3.1 enabled xsrf so use notebooks ajax that includes the | ||
// xsrf token in the header data | ||
|
||
var course_html = $([ | ||
'<div id="courses" class="tab-pane">', | ||
' <div class="alert alert-danger version_error">', | ||
' </div>', | ||
' <div class="panel-group">', | ||
' <div class="panel panel-default">', | ||
' <div class="panel-heading">', | ||
' Available formgraders', | ||
' <span id="formgrader_buttons" class="pull-right toolbar_buttons">', | ||
' <button id="refresh_formgrader_list" title="Refresh formgrader list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>', | ||
' </span>', | ||
' </div>', | ||
' <div class="panel-body">', | ||
' <div id="formgrader_list" class="list_container">', | ||
' <div id="formgrader_list_placeholder" class="row list_placeholder">', | ||
' <div> There are no available formgrader services. </div>', | ||
' </div>', | ||
' <div id="formgrader_list_loading" class="row list_loading">', | ||
' <div> Loading, please wait... </div>', | ||
' </div>', | ||
' <div id="formgrader_list_error" class="row list_error">', | ||
' <div></div>', | ||
' </div>', | ||
' </div>', | ||
' </div>', | ||
' </div>', | ||
' </div> ', | ||
'</div>' | ||
].join('\n')); | ||
|
||
function checkNbGraderVersion(base_url) { | ||
var settings = { | ||
cache : false, | ||
type : "GET", | ||
dataType : "json", | ||
data : { | ||
version: nbgrader_version | ||
}, | ||
success : function (response) { | ||
if (!response['success']) { | ||
var err = $("#courses .version_error"); | ||
err.text(response['message']); | ||
err.show(); | ||
} | ||
}, | ||
error : utils.log_ajax_error, | ||
}; | ||
var url = utils.url_path_join(base_url, 'nbgrader_version'); | ||
ajax(url, settings); | ||
} | ||
|
||
function load() { | ||
if (!Jupyter.notebook_list) return; | ||
var base_url = Jupyter.notebook_list.base_url; | ||
$('head').append( | ||
$('<link>') | ||
.attr('rel', 'stylesheet') | ||
.attr('type', 'text/css') | ||
.attr('href', base_url + 'nbextensions/course_list/course_list.css') | ||
); | ||
$(".tab-content").append(course_html); | ||
$("#tabs").append( | ||
$('<li>') | ||
.append( | ||
$('<a>') | ||
.attr('href', '#courses') | ||
.attr('data-toggle', 'tab') | ||
.text('Courses') | ||
.click(function (e) { | ||
window.history.pushState(null, null, '#courses'); | ||
course_list.load_list(); | ||
}) | ||
) | ||
); | ||
var course_list = new CourseList.CourseList( | ||
'#formgrader_list', | ||
'#refresh_formgrader_list', | ||
{ | ||
base_url: Jupyter.notebook_list.base_url | ||
} | ||
); | ||
checkNbGraderVersion(base_url); | ||
} | ||
return { | ||
load_ipython_extension: load | ||
}; | ||
}); |
Oops, something went wrong.