Commit f0258b8d by Brian Wilson

first pass at pdfbook

parent 9b6cbd6d
......@@ -352,6 +352,13 @@ class CourseDescriptor(SequenceDescriptor):
"""
return self.metadata.get('tabs')
@property
def pdf_textbooks(self):
"""
Return the pdf_textbooks config, as a python object, or None if not specified.
"""
return self.metadata.get('pdf_textbooks')
@tabs.setter
def tabs(self, value):
self.metadata['tabs'] = value
......
......@@ -119,6 +119,16 @@ def _textbooks(tab, user, course, active_page):
for index, textbook in enumerate(course.textbooks)]
return []
def _pdf_textbooks(tab, user, course, active_page):
"""
Generates one tab per textbook. Only displays if user is authenticated.
"""
if user.is_authenticated():
# since there can be more than one textbook, active_page is e.g. "book/0".
return [CourseTab(textbook['tab_title'], reverse('pdf_book', args=[course.id, index]),
active_page == "pdftextbook/{0}".format(index))
for index, textbook in enumerate(course.pdf_textbooks)]
return []
def _staff_grading(tab, user, course, active_page):
if has_access(user, course, 'staff'):
......@@ -198,6 +208,7 @@ VALID_TAB_TYPES = {
'discussion': TabImpl(need_name, _discussion),
'external_link': TabImpl(key_checker(['name', 'link']), _external_link),
'textbooks': TabImpl(null_validator, _textbooks),
'pdf_textbooks': TabImpl(null_validator, _pdf_textbooks),
'progress': TabImpl(need_name, _progress),
'static_tab': TabImpl(key_checker(['name', 'url_slug']), _static_tab),
'peer_grading': TabImpl(null_validator, _peer_grading),
......
......@@ -30,3 +30,23 @@ def index(request, course_id, book_index, page=None):
def index_shifted(request, course_id, page):
return index(request, course_id=course_id, page=int(page) + 24)
@login_required
def pdf_index(request, course_id, book_index, chapter=None, page=None):
course = get_course_with_access(request.user, course_id, 'load')
staff_access = has_access(request.user, course, 'staff')
book_index = int(book_index)
textbook = course.pdf_textbooks[book_index]
# if page is None:
# page = textbook.start_page
return render_to_response('static_pdfbook.html',
{'book_index': book_index,
'course': course,
'textbook': textbook,
'page': page,
'chapter': chapter,
'staff_access': staff_access})
<%inherit file="main.html" />
<%namespace name='static' file='static_content.html'/>
<%block name="title"><title>${course.number} Textbook</title></%block>
<%block name="headextra">
<%static:css group='course'/>
<%static:js group='courseware'/>
</%block>
<%block name="js_extra">
<!-- Use latest PDF.js build from Github -->
<script type="text/javascript" src="https://raw.github.com/mozilla/pdf.js/gh-pages/build/pdf.js"></script>
<script type="text/javascript">
//
// NOTE:
// Modifying the URL below to another server will likely *NOT* work. Because of browser
// security restrictions, we have to use a file server with special headers
// (CORS) - most servers don't support cross-origin browser requests.
//
var url = "${textbook['url']}";
//
// Disable workers to avoid yet another cross-origin issue (workers need the URL of
// the script to be loaded, and currently do not allow cross-origin scripts)
//
PDFJS.disableWorker = true;
var pdfDoc = null,
pageNum = 1,
scale = 0.8,
canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
//
// Get page info from document, resize canvas accordingly, and render page
//
function renderPage(num) {
// Using promise to fetch the page
pdfDoc.getPage(num).then(function(page) {
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext);
});
// Update page counters
document.getElementById('page_num').textContent = pageNum;
document.getElementById('page_count').textContent = pdfDoc.numPages;
}
//
// Go to previous page
//
function goPrevious() {
if (pageNum <= 1)
return;
pageNum--;
renderPage(pageNum);
}
//
// Go to next page
//
function goNext() {
if (pageNum >= pdfDoc.numPages)
return;
pageNum++;
renderPage(pageNum);
}
//
// Asynchronously download PDF as an ArrayBuffer
//
PDFJS.getDocument(url).then(function getPdfHelloWorld(_pdfDoc) {
pdfDoc = _pdfDoc;
renderPage(pageNum);
});
</script>
</%block>
<!-- TODO: what should active_page be set to here???? textbook/0 or pdftextbook/0? -->
<%include file="/courseware/course_navigation.html" args="active_page='textbook/{0}'.format(book_index)" />
<section class="container">
<div class="book-wrapper">
<section class="book">
<section class="page">
<div>
<button id="prev" onclick="goPrevious()">Previous</button>
<button id="next" onclick="goNext()">Next</button>
&nbsp; &nbsp;
<span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
</div>
<div>
<canvas id="the-canvas" style="border:1px solid black"></canvas>
</div>
</section>
</section>
</div>
</section>
......@@ -233,6 +233,17 @@ if settings.COURSEWARE_ENABLED:
'staticbook.views.index'),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/book-shifted/(?P<page>[^/]*)$',
'staticbook.views.index_shifted'),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>[^/]*)/$',
'staticbook.views.pdf_index', name="pdf_book"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>[^/]*)/(?P<page>[^/]*)$',
'staticbook.views.pdf_index'),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>[^/]*)/chapter/(?P<chapter>[^/]*)/$',
'staticbook.views.pdf_index'),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>[^/]*)/chapter/(?P<chapter>[^/]*)/(?P<page>[^/]*)$',
'staticbook.views.pdf_index'),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/?$',
'courseware.views.index', name="courseware"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/(?P<chapter>[^/]*)/$',
......@@ -241,6 +252,7 @@ if settings.COURSEWARE_ENABLED:
'courseware.views.index', name="courseware_section"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/(?P<chapter>[^/]*)/(?P<section>[^/]*)/(?P<position>[^/]*)/?$',
'courseware.views.index', name="courseware_position"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/progress$',
'courseware.views.progress', name="progress"),
# Takes optional student_id for instructor use--shows profile as that student sees it.
......
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