from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from karmaworld.apps.notes.models import UserUploadMapping
from karmaworld.apps.notes.models import NoteMarkdown
-from karmaworld.apps.quizzes.find_keywords import find_keywords
from karmaworld.apps.quizzes.models import Keyword
from karmaworld.apps.users.models import NoteKarmaEvent
import os
note_markdown = NoteMarkdown(note=note, markdown=markdown)
note_markdown.save()
- # Guess some keywords from the note text
- keywords = find_keywords(note.text)
- for word in keywords:
- Keyword.objects.create(word=word, note=note)
-
# If we know the user who uploaded this,
# associate them with the note
if user:
# return a url ending in id
return reverse('note_keywords', args=[self.course.school.slug, self.course.slug, self.id])
+ def get_absolute_quiz_url(self):
+ """ Resolve note url, use 'note' route and slug if slug
+ otherwise use note.id
+ """
+ if self.slug is not None:
+ # return a url ending in slug
+ if self.course.school:
+ return reverse('note_quiz', args=[self.course.school.slug, self.course.slug, self.slug])
+ else:
+ return reverse('note_quiz', args=[self.course.department.school.slug, self.course.slug, self.slug])
+ else:
+ # return a url ending in id
+ return reverse('note_quiz', args=[self.course.school.slug, self.course.slug, self.id])
def filter_html(self, html):
"""
from django.forms.formsets import formset_factory
from karmaworld.apps.courses.models import Course
from karmaworld.apps.notes.search import SearchIndex
+from karmaworld.apps.quizzes.create_quiz import quiz_from_keywords
from karmaworld.apps.quizzes.find_keywords import find_keywords
from karmaworld.apps.quizzes.forms import KeywordForm
from karmaworld.apps.quizzes.models import Keyword
from karmaworld.utils.ajax_utils import *
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
-from django.views.generic import DetailView, ListView
+from django.views.generic import DetailView, ListView, TemplateView
from django.views.generic import FormView
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
""" Class-based view for the note html page """
model = Note
context_object_name = u"note" # name passed to template
+ template_name = 'notes/note_base.html'
def get_context_data(self, **kwargs):
""" Generate custom context for the page rendering a Note
"""
form_class = NoteForm
model = Note
- template_name = 'notes/note_detail.html'
+ template_name = 'notes/note_base.html'
def post(self, request, *args, **kwargs):
self.object = self.get_object()
model = Note
context_object_name = u"note" # name passed to template
form_class = formset_factory(KeywordForm)
- template_name = 'notes/note_detail.html'
+ template_name = 'notes/note_base.html'
def get_object(self, queryset=None):
return Note.objects.get(slug=self.kwargs['slug'])
keyword_object.save()
+class NoteQuizView(TemplateView):
+ template_name = 'notes/note_base.html'
+
+ def get_context_data(self, **kwargs):
+ note = Note.objects.get(slug=self.kwargs['slug'])
+
+ note_page_context_helper(note, self.request, kwargs)
+
+ kwargs['note'] = note
+ kwargs['questions'] = quiz_from_keywords(note)
+ kwargs['show_quiz'] = True
+
+ return super(NoteQuizView, self).get_context_data(**kwargs)
+
+
class NoteSearchView(ListView):
template_name = 'notes/search_results.html'
# -*- coding:utf8 -*-
# Copyright (C) 2014 FinalsClub Foundation
from django.contrib import admin
-from karmaworld.apps.quizzes.models import MultipleChoiceQuestion, FlashCardQuestion, MultipleChoiceOption, Quiz, \
- TrueFalseQuestion, Keyword
-from nested_inlines.admin import NestedTabularInline, NestedModelAdmin, NestedStackedInline
+from karmaworld.apps.quizzes.models import Keyword
-
-class MultipleChoiceOptionInlineAdmin(NestedTabularInline):
- model = MultipleChoiceOption
-
-
-class MultipleChoiceQuestionAdmin(NestedModelAdmin):
- model = MultipleChoiceQuestion
- inlines = [MultipleChoiceOptionInlineAdmin]
- list_display = ('question_text', 'quiz')
-
-
-class MultipleChoiceQuestionInlineAdmin(NestedStackedInline):
- model = MultipleChoiceQuestion
- list_display = ('question_text', 'quiz')
-
-
-class FlashCardQuestionInlineAdmin(NestedStackedInline):
- model = FlashCardQuestion
- list_display = ('keyword_side', 'definition_side', 'quiz')
-
-
-class TrueFalseQuestionInlineAdmin(NestedStackedInline):
- model = TrueFalseQuestion
- list_display = ('question_text', 'quiz')
-
-
-class QuizAdmin(NestedModelAdmin):
- search_fields = ['name', 'note__name']
- list_display = ('name', 'note')
- inlines = [MultipleChoiceQuestionInlineAdmin, TrueFalseQuestionInlineAdmin, FlashCardQuestionInlineAdmin]
-
-
-admin.site.register(Quiz, QuizAdmin)
-admin.site.register(MultipleChoiceQuestion, MultipleChoiceQuestionAdmin)
-admin.site.register(MultipleChoiceOption)
-admin.site.register(FlashCardQuestion)
-admin.site.register(TrueFalseQuestion)
admin.site.register(Keyword)
--- /dev/null
+import random
+from karmaworld.apps.quizzes.models import Keyword
+
+
+class BaseQuizQuestion(object):
+
+ def question_type(self):
+ return self.__class__.__name__
+
+
+class MultipleChoiceQuestion(BaseQuizQuestion):
+ def __init__(self, question_text, choices):
+ self.question_text = question_text
+ self.choices = choices
+
+ def __unicode__(self):
+ return "Multiple choice: {0}: {1}".format(self.question_text, ", ".join(map(str, self.choices)))
+
+ def __str__(self):
+ return unicode(self)
+
+ def __repr__(self):
+ return str(self)
+
+
+class MultipleChoiceOption(object):
+ def __init__(self, text, correct):
+ self.text = text
+ self.correct = correct
+
+ def __unicode__(self):
+ return self.text
+
+ def __str__(self):
+ return unicode(self)
+
+ def __repr__(self):
+ return str(self)
+
+
+class FlashCardQuestion(BaseQuizQuestion):
+ def __init__(self, keyword_side, definition_side):
+ self.keyword_side = keyword_side
+ self.definition_side = definition_side
+
+ def __unicode__(self):
+ return "Flash card: {0} / {1}".format(self.keyword_side, self.definition_side)
+
+ def __str__(self):
+ return unicode(self)
+
+ def __repr__(self):
+ return str(self)
+
+
+class TrueFalseQuestion(BaseQuizQuestion):
+ def __init__(self, question_text, true):
+ self.question_text = question_text
+ self.true = true
+
+ def __unicode__(self):
+ return "True or false: {0}".format(self.question_text)
+
+ def __str__(self):
+ return unicode(self)
+
+ def __repr__(self):
+ return str(self)
+
+
+KEYWORD_MULTIPLE_CHOICE = 1
+DEFINITION_MULTIPLE_CHOICE = 2
+KEYWORD_DEFINITION_TRUE_FALSE = 3
+GENERATED_QUESTION_TYPE = (
+ KEYWORD_MULTIPLE_CHOICE,
+ DEFINITION_MULTIPLE_CHOICE,
+ KEYWORD_DEFINITION_TRUE_FALSE,
+)
+
+MULTIPLE_CHOICE_CHOICES = 4
+
+
+def _create_keyword_multiple_choice(keyword, keywords):
+ choices = [MultipleChoiceOption(text=keyword.word, correct=True)]
+
+ for other_keyword in random.sample(keywords.exclude(id=keyword.id), MULTIPLE_CHOICE_CHOICES - 1):
+ choices.append(MultipleChoiceOption(
+ text=other_keyword.word,
+ correct=False))
+
+ question_text = 'Pick the keyword to match "{d}"'.format(d=keyword.definition)
+
+ return MultipleChoiceQuestion(question_text, choices)
+
+
+def _create_definition_multiple_choice(keyword, keywords):
+ choices = [MultipleChoiceOption(text=keyword.definition, correct=True)]
+
+ for other_keyword in random.sample(keywords.exclude(id=keyword.id), MULTIPLE_CHOICE_CHOICES - 1):
+ choices.append(MultipleChoiceOption(
+ text=other_keyword.definition,
+ correct=False))
+
+ question_text = 'Pick the definition to match "{w}"'.format(w=keyword.word)
+
+ return MultipleChoiceQuestion(question_text, choices)
+
+
+def _create_keyword_definition_true_false(keyword, keywords):
+ true = random.choice((True, False))
+
+ if true:
+ definition = keyword.definition
+ else:
+ other_keyword = random.choice(keywords.exclude(id=keyword.id))
+ definition = other_keyword.definition
+
+ question_text = 'The keyword "{w}" matches the definition "{d}"'. \
+ format(w=keyword.word, d=definition)
+
+ return TrueFalseQuestion(question_text, true)
+
+
+def _create_keyword_flashcard_blank(keyword):
+ return FlashCardQuestion(keyword.definition, keyword.word)
+
+
+def quiz_from_keywords(note):
+ keywords = Keyword.objects.filter(note=note)
+ questions = []
+
+ for keyword in keywords:
+ if keyword.word and keyword.definition:
+ question_type = random.choice(GENERATED_QUESTION_TYPE)
+
+ if question_type is KEYWORD_MULTIPLE_CHOICE:
+ questions.append(_create_keyword_multiple_choice(keyword, keywords))
+
+ elif question_type is DEFINITION_MULTIPLE_CHOICE:
+ questions.append(_create_definition_multiple_choice(keyword, keywords))
+
+ elif question_type is KEYWORD_DEFINITION_TRUE_FALSE:
+ questions.append(_create_keyword_definition_true_false(keyword, keywords))
+
+ return questions
+
+
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding:utf8 -*-
-# Copyright (C) 2014 FinalsClub Foundation
-from __future__ import division
-from collections import defaultdict
-import nltk
-import itertools
-from operator import itemgetter
-from pygraph.classes.digraph import digraph
-from pygraph.algorithms.pagerank import pagerank
-from pygraph.classes.exceptions import AdditionError
-
-
-def _filter(tagged, tags=('NN', 'JJ', 'NNP')):
- pos_filtered = [item[0] for item in tagged if item[1] in tags]
- stopwords_filtered = [word.lower() for word in pos_filtered if not word.lower() in nltk.corpus.stopwords.words('english')]
- remove_punc = [item.replace('.', '') for item in stopwords_filtered]
- return remove_punc
-
-
-def _normalize(words):
- lower = [word.lower() for word in words]
- remove_punc = [item.replace('.', '') for item in lower]
- return remove_punc
-
-
-def _unique_everseen(iterable, key=None):
- "List unique elements, preserving order. Remember all elements ever seen."
- # unique_everseen('AAAABBBCCDAABBB') --> A B C D
- # unique_everseen('ABBCcAD', str.lower) --> A B C D
- seen = set()
- seen_add = seen.add
- if key is None:
- for element in itertools.ifilterfalse(seen.__contains__, iterable):
- seen_add(element)
- yield element
- else:
- for element in iterable:
- k = key(element)
- if k not in seen:
- seen_add(k)
- yield element
-
-
-def _common_ngrams(normalized_words, top_ordered_keywords, n):
- ngrams_in_top_keywords = set()
- common_ngrams = []
-
- for ngram_words in itertools.product(top_ordered_keywords, repeat=n):
- target_ngram = list(ngram_words)
- for i in range(len(normalized_words)):
- ngram = normalized_words[i:i+n]
- if target_ngram == ngram:
- ngrams_in_top_keywords.add(tuple(target_ngram))
-
- for words in ngrams_in_top_keywords:
- words_usage_in_ngram = 0
- individual_word_usage = defaultdict(lambda: 0)
- for i in range(len(normalized_words)):
- for word in words:
- if normalized_words[i] == word:
- individual_word_usage[word] += 1
- if normalized_words[i:i+n] == list(words):
- words_usage_in_ngram += 1
-
- for word in words:
- ratio = words_usage_in_ngram / individual_word_usage[word]
- if ratio > 0.5:
- common_ngrams.append(words)
- break
-
- return common_ngrams
-
-
-def find_keywords(document, word_count=10):
- """
- Credit to https://gist.github.com/voidfiles/1646117
- and http://acl.ldc.upenn.edu/acl2004/emnlp/pdf/Mihalcea.pdf
- """
- sentences = nltk.sent_tokenize(document)
- candidate_words = []
- all_words = []
- for sentence in sentences:
- words = nltk.word_tokenize(sentence)
- all_words.extend(words)
- tagged_words = nltk.pos_tag(words)
- filtered_words = _filter(tagged_words)
- candidate_words.extend(filtered_words)
-
- unique_word_set = _unique_everseen(candidate_words)
-
- gr = digraph()
- gr.add_nodes(list(unique_word_set))
-
- window_start = 0
- window_end = 2
-
- while 1:
- window_words = candidate_words[window_start:window_end]
- if len(window_words) == 2:
- try:
- gr.add_edge((window_words[0], window_words[1]))
- except AdditionError:
- pass
- else:
- break
-
- window_start += 1
- window_end += 1
-
- calculated_page_rank = pagerank(gr)
- di = sorted(calculated_page_rank.iteritems(), key=itemgetter(1), reverse=True)
- all_ordered_keywords = [w[0] for w in di]
- top_ordered_keywords = all_ordered_keywords[:word_count]
-
- normalized_words = _normalize(all_words)
-
- common_bigrams = _common_ngrams(normalized_words, top_ordered_keywords, 2)
- common_trigrams = _common_ngrams(normalized_words, top_ordered_keywords, 3)
- for words in common_bigrams + common_trigrams:
- for word in words:
- top_ordered_keywords.remove(word)
- top_ordered_keywords.insert(0, ' '.join(words))
-
- return top_ordered_keywords
def __unicode__(self):
return self.word
-
-class Quiz(models.Model):
- name = models.CharField(max_length=512)
- note = models.ForeignKey('notes.Note', blank=True, null=True)
- timestamp = models.DateTimeField(default=datetime.datetime.utcnow)
-
- class Meta:
- verbose_name_plural = 'quizzes'
-
- def __unicode__(self):
- return self.name
-
-
-class BaseQuizQuestion(models.Model):
- quiz = models.ForeignKey(Quiz)
- timestamp = models.DateTimeField(default=datetime.datetime.utcnow)
-
- explanation = models.CharField(max_length=2048, blank=True, null=True)
-
- EASY = 'EASY'
- MEDIUM = 'MEDIUM'
- HARD = 'HARD'
- DIFFICULTY_CHOICES = (
- (EASY, 'Easy'),
- (MEDIUM, 'Medium'),
- (HARD, 'Hard'),
- )
-
- difficulty = models.CharField(max_length=50, choices=DIFFICULTY_CHOICES, blank=True, null=True)
-
- UNDERSTAND = 'UNDERSTAND'
- REMEMBER = 'REMEMBER'
- ANALYZE = 'ANALYZE'
- KNOWLEDGE = 'KNOWLEDGE'
- CATEGORY_CHOICES = (
- (UNDERSTAND, 'Understand'),
- (REMEMBER, 'Remember'),
- (ANALYZE, 'Analyze'),
- (KNOWLEDGE, 'Knowledge'),
- )
-
- category = models.CharField(max_length=50, choices=CATEGORY_CHOICES, blank=True, null=True)
-
-
- class Meta:
- abstract = True
-
-
-class MultipleChoiceQuestion(BaseQuizQuestion):
- question_text = models.CharField(max_length=2048)
-
- class Meta:
- verbose_name = 'Multiple choice question'
-
- def __unicode__(self):
- return self.question_text
-
-
-class MultipleChoiceOption(models.Model):
- text = models.CharField(max_length=2048)
- correct = models.BooleanField()
- question = models.ForeignKey(MultipleChoiceQuestion, related_name="choices")
-
- def __unicode__(self):
- return self.text
-
-
-class FlashCardQuestion(BaseQuizQuestion):
- keyword_side = models.CharField(max_length=2048, verbose_name='Keyword')
- definition_side = models.CharField(max_length=2048, verbose_name='Definition')
-
- class Meta:
- verbose_name = 'Flash card question'
-
- def __unicode__(self):
- return self.keyword_side + ' / ' + self.definition_side
-
-
-class TrueFalseQuestion(BaseQuizQuestion):
- text = models.CharField(max_length=2048)
- true = models.BooleanField(verbose_name='True?')
-
- class Meta:
- verbose_name = 'True/False question'
-
- def __unicode__(self):
- return self.text
-
-ALL_QUESTION_CLASSES = (MultipleChoiceQuestion, FlashCardQuestion, TrueFalseQuestion)
-ALL_QUESTION_CLASSES_NAMES = {
- MultipleChoiceQuestion.__name__: MultipleChoiceQuestion,
- FlashCardQuestion.__name__: FlashCardQuestion,
- TrueFalseQuestion.__name__: TrueFalseQuestion,
-}
-
padding: 5px;
}
-#keyword-intro {
+#keyword-intro,
+#quiz-intro {
font-size: 0.8em;
}
+#quiz-intro {
+ margin-bottom: 10px;
+}
+
#note-category {
margin-bottom: 10px;
}
+.quiz-question {
+ margin-bottom: 20px;
+}
+
+.quiz-question-inner {
+ padding: 10px 0 10px 0;
+}
+
+.question-text {
+ margin: 0 0 10px 0;
+}
+
+.quiz-question input[type="radio"]:checked+label {
+ font-weight: bold;
+}
+
+.correct {
+ background-color: #e5ffdc;
+}
+
+.incorrect {
+ background-color: #ffdcdc;
+}
+
+.correct-label,
+.incorrect-label {
+ padding-left: 0;
+}
+
+.correct-label-inner,
+.incorrect-label-inner {
+ color: #ffffff;
+ font-weight: bold;
+ padding: 5px 10px 5px 10px;
+ font-size: 0.8em;
+ width: intrinsic; /* Safari/WebKit uses a non-standard name */
+ width: -moz-max-content; /* Firefox/Gecko */
+}
+
+.correct-label-inner {
+ background-color: #4f7342;
+}
+
+.incorrect-label-inner {
+ background-color: #740b00;
+}
+
});
// wire up search box
- $('input.search-courses').keyup(function() {
+ $('#search-courses').keyup(function() {
dataTable.fnFilter($(this).val());
});
}
+function markQuestionCorrect(question) {
+ question.find('.quiz-question').addClass('correct');
+ question.find('.quiz-question').removeClass('incorrect');
+ question.find('.correct-label').show();
+ question.find('.incorrect-label').hide();
+}
+
+function markQuestionIncorrect(question) {
+ question.find('.quiz-question').addClass('incorrect');
+ question.find('.quiz-question').removeClass('correct');
+ question.find('.incorrect-label').show();
+ question.find('.correct-label').hide();
+}
+
+function initQuizPage() {
+ $('#check-answers-button').click(function() {
+ $('.quiz-question-wrapper').each(function() {
+ var choice = $(this).find('input:checked');
+ if (choice.length) {
+ console.log(choice);
+ if (choice.data('correct') == true) {
+ markQuestionCorrect($(this));
+ } else {
+ markQuestionIncorrect($(this));
+ }
+ }
+ });
+ });
+}
<button id="add-course-btn" class="inline-button important museo700" data-reveal-id="add-course-form">Add a Course</button>
</div>
<div class="small-12 large-9 columns">
- <span><input class="search adelle-sans" type="text" placeholder="Search Courses and Schools" />
+ <span><input id="search-courses" class="search adelle-sans" type="text" placeholder="Search Courses and Schools" />
<i class="fa fa-search inline search-icon"></i></span>
</div>
</div>
--- /dev/null
+{% extends "base.html" %}
+{% load url from future %}
+{% load compress %}
+
+{% block title %}
+ {{ note.name }}
+{% endblock %}
+
+{% block pagestyle %}
+ {% compress css %}
+ <link rel="stylesheet" type="text/css" media="all" href="{{ STATIC_URL }}css/note_course_pages.css">
+ <link rel="stylesheet" type="text/css" media="all" href="{{ STATIC_URL }}css/annotator.min.css" />
+ {% endcompress %}
+{% endblock %}
+
+{% block pagescripts %}
+ <script type="text/javascript">
+ var note_id = {{ note.id }};
+ var note_thank_url = "{% url 'thank_note' note.id %}"
+ var note_flag_url = "{% url 'flag_note' note.id %}"
+ var edit_note_tags_url = "{% url 'edit_note_tags' note.id %}"
+ var note_downloaded_url = "{% url 'downloaded_note' note.id %}"
+ var note_contents_url = "{{ S3_URL }}{{ note.get_relative_s3_path }}"
+ var pdfControls = {% if pdf_controls %} true {% else %} false {% endif %};
+ var csrf_token = "{{ csrf_token }}";
+ var annotator_js_url = "{{ STATIC_URL }}js/annotator-full.min.js";
+ var annotator_css_url = "{{ STATIC_URL }}css/annotator.min.css";
+ var setup_ajax_url = "{{ STATIC_URL }}js/setup-ajax.js";
+ var note_edit_url = "{% url 'edit_note' note.id %}";
+ var user_authenticated = {% if user.is_authenticated %}true{% else %}false{% endif %};
+ </script>
+ {% compress js %}
+ <script src="{{ STATIC_URL }}js/setup-ajax.js"></script>
+ <script src="{{ STATIC_URL }}js/note-detail.js" ></script>
+ <script src="{{ STATIC_URL }}js/pxem.jQuery.js"></script>
+ <script src="{{ STATIC_URL }}js/marked.js" ></script>
+ <script src="{{ STATIC_URL }}js/annotator-full.min.js"></script>
+ {% endcompress %}
+ <script>
+ {% if show_note_container %}
+ $(function() {
+ $(document).foundation('joyride', 'start');
+ initNoteContentPage();
+ });
+ {% endif %}
+
+ {% if show_keywords %}
+ $(function() {
+ initNoteKeywordsPage();
+ });
+ {% endif %}
+
+ {% if show_quiz %}
+ $(function() {
+ initQuizPage();
+ });
+ {% endif %}
+ </script>
+{% endblock %}
+
+{% block raw_content %}
+ <section id="note_content">
+
+ <div class="return-to-course show-for-large-up">
+ <div class="row">
+ <div class="small-12 columns">
+ <a href="{{ note.course.get_absolute_url }}" class="inherit-color">
+ <i class="fa fa-angle-double-left"></i> See all notes for {{ note.course.name }}
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div id="note_header">
+
+ <div class="row header-byline">
+ <div class="small-12 columns">
+ <strong>Lecture note for {{ note.course.name }} </strong>
+ at
+ {% if note.course.department.school %}
+ {{ note.course.department.school.name }}
+ {% else %}
+ {{ note.course.school.name }}
+ {% endif %}
+
+ <span style="display: inline;"><span class="show-for-large-up"><i class="fa fa-thumbs-up"></i> <span id="thank-number">{{ note.thanks }}</span> Thank{{ note.thanks|pluralize }}</span></span>
+ </div>
+ </div>
+
+ <div class="row museo700">
+ <div class="small-12 columns header-title-row">
+ <span class="header-title">{{ note.name }} </span>
+ <span style="display: inline;">
+ <span class="show-for-large-up">
+ {% if user.is_authenticated %}
+ {% if already_thanked %}
+ <button id="thank-button-disabled" class="modify-button disabled opentip"
+ data-ot="You've already thanked this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-thumbs-up"></i> Thank Note</button>
+ {% else %}
+ <button id="thank-button" class="modify-button"><i class="fa fa-thumbs-up"></i> Thank Note</button>
+ <button id="thank-button-disabled" class="modify-button disabled opentip hide"
+ data-ot="You've already thanked this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-thumbs-up"></i> Thank Note</button>
+ {% endif %}
+ {% else %}
+ <button id="thank-button-disabled" class="modify-button disabled opentip"
+ data-ot="Log in to thank this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-thumbs-up"></i> Thank Note</button>
+ {% endif %}
+
+ {% if user.is_authenticated %}
+ {% if already_flagged %}
+ <button id="flag-button-disabled" class="modify-button disabled opentip"
+ data-ot="You've already reported this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-flag"></i> Report Note</button>
+ {% else %}
+ <button id="flag-button" class="modify-button"><i class="fa fa-flag"></i> Report Note</button>
+ <button id="flag-button-disabled" class="modify-button disabled opentip hide"
+ data-ot="You've already reported this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-flag"></i> Report Note</button>
+ {% endif %}
+ {% else %}
+ <button id="flag-button-disabled" class="modify-button disabled opentip"
+ data-ot="Log in to report this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-flag"></i> Report Note</button>
+ {% endif %}
+
+ {% if user.is_authenticated %}
+ <a href="{{ note.get_fp_url }}">
+ <button id="note-download-button" class="modify-button opentip"
+ data-ot="It costs 2 karma points to download a note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-download"></i> Download Note</button></a>
+ {% else %}
+ <button id="note-download-button-disabled" class="modify-button disabled opentip"
+ data-ot="Log in to download this note"
+ {% include 'partial/opentip_settings.html' %}>
+ <i class="fa fa-download"></i> Download Note</button>
+ {% endif %}
+
+ {% if user.get_profile.can_edit_items and note.user != user %}
+ <button id="edit-note-tags" class="modify-button" data-reveal-id="note-tag-dialog">
+ <i class="fa fa-pencil-square-o"></i> Edit Tags
+ </button>
+ {% endif %}
+
+ {% if note.user == request.user %}
+ <button id="edit-button" data-reveal-id="note-edit-dialog" class="modify-button"> <i class="fa fa-edit"></i> Edit This Note</button>
+ {% endif %}
+
+ {% if note.license %}
+ {{ note.license.html|safe }} {% if note.upstream_link %}<a href="{{ note.upstream_link }}" target="_blank">{{ note.upstream_link|slice:":80" }}</a>{% endif %}
+ {% endif %}
+ </span>
+ </span>
+ </div>
+ </div>
+
+ {% if note.category %}
+ <div id="note-category" class="row show-for-large-up">
+ <div class="small-12 columns">
+ <em>{{ note.get_category_display }}</em>
+ </div>
+ </div>
+ {% endif %}
+
+ <div id="note-tags" class="row show-for-large-up">
+ <div class="small-12 columns">
+ <strong>Tags: </strong>
+ <span class="tags">
+ {% if note.tags.all %}
+ {% for tag in note.tags.all %}
+ <span class="tag-span">
+ {{ tag.name }}{% if not forloop.last %}, {% endif %}
+ </span>
+ {% endfor %}
+ {% else %}
+ <em class="light">(none defined yet)</em>
+ {% endif %}
+ </span>
+ </div><!-- /note_tags -->
+ </div>
+
+ <div id="note-tag-dialog" class="reveal-modal" data-reveal>
+ <a class="close-reveal-modal">×</a>
+ <div class="row">
+ <div class="small-12 columns">
+ <h3>Edit this note's tags</h3>
+ <input id="note_tags_input" type="text" value="{% for tag in note.tags.all %}{{ tag.name }}{% if not forloop.last %}, {% endif %}{% endfor %}">
+ <button id="save_note_tags" type="submit" value="tags-form"><i class="fa fa-save"></i> Save</button>
+ </div>
+ </div>
+ </div>
+
+ <div id="note-edit-dialog" class="reveal-modal" data-reveal>
+ <a class="close-reveal-modal">×</a>
+ <div class="row">
+ <div class="small-8 columns">
+ <h3>Edit Your Note</h3>
+ </div>
+ <div class="small-4 columns text-right">
+ <form method="POST" action="{% url 'note_delete' %}">
+ {% csrf_token %}
+ {{ note_delete_form }}
+ <button id="delete-note-button" type="submit" class="scary"><i class="fa fa-trash-o"></i> Delete Note</button>
+ </form>
+ </div>
+ </div>
+ <div class="row">
+ <form method="POST" action="{{ note.get_absolute_url }}">
+ {% csrf_token %}
+ <div class="small-12 large-6 columns">
+ {% with note_edit_form.name as field %}
+ {{ field.errors|safe }}
+ <label for="{{ field.id_for_label }}">{{ field.label }}:</label>
+ {{ field }}
+ <p>{{ field.help_text }}</p>
+ {% endwith %}
+ </div>
+ <div class="small-12 large-6 columns">
+ {% with note_edit_form.tags as field %}
+ {{ field.errors|safe }}
+ <label for="{{ field.id_for_label }}">{{ field.label }}:</label>
+ {{ field }}
+ <p>{{ field.help_text }}</p>
+ {% endwith %}
+ </div>
+ <div class="small-12 columns text-center">
+ <button type="submit"><i class="fa fa-save"></i> Save</button>
+ </div>
+ </form>
+ </div>
+ </div>
+
+ </div><!-- /note header -->
+
+ <div class="row">
+ <div id="tabs" class="small-12 columns">
+ <dl class="tabs">
+ <dd id="note-tab-button" class="{% if show_note_container %}active{% endif %}">
+ <a href="{{ note.get_absolute_url }}">Note</a>
+ </dd>
+ <dd id="keywords-tab-button" class="{% if show_keywords %}active{% endif %}">
+ <a href="{{ note.get_absolute_keywords_url }}">Key Terms & Definitions</a>
+ </dd>
+ <dd id="quiz-tab-button" class="{% if show_quiz %}active{% endif %}">
+ <a href="{{ note.get_absolute_quiz_url }}">Quiz Questions</a>
+ </dd>
+ </dl>
+ <div class="tabs-content">
+ </div>
+ {% if show_note_container %}
+ {% include 'notes/note_detail.html' %}
+ {% endif %}
+ {% if show_keywords %}
+ {% include 'notes/note_keywords.html' %}
+ {% endif %}
+ {% if show_quiz %}
+ {% include 'notes/note_quiz.html' %}
+ {% endif %}
+ </div>
+ </div>
+
+ </section><!--/note_content-->
+
+ <ol class="joyride-list" data-joyride
+ data-options="cookie_monster: true; cookie_name: note_detail_joyride">
+ <li data-id="note-content-wrapper" data-text="Awesome!" data-options="tip_location: top">
+ <p>You can highlight important words or phrases in this note to add definitions for them.</p>
+ </li>
+ <li data-id="keywords-tab-button" data-text="Awesome!" data-options="tip_location: top">
+ <p>Keywords you define will appear here, and you can define new ones here too.</p>
+ </li>
+ </ol>
+
+{% endblock %}
+
+
-{% extends "base.html" %}
-{% load url from future %}
-{% load compress %}
-
-{% block title %}
- {{ note.name }}
-{% endblock %}
-
-{% block pagestyle %}
- {% compress css %}
- <link rel="stylesheet" type="text/css" media="all" href="{{ STATIC_URL }}css/note_course_pages.css">
- <link rel="stylesheet" type="text/css" media="all" href="{{ STATIC_URL }}css/annotator.min.css" />
- {% endcompress %}
-{% endblock %}
-
-{% block pagescripts %}
- <script type="text/javascript">
- var note_id = {{ note.id }};
- var note_thank_url = "{% url 'thank_note' note.id %}"
- var note_flag_url = "{% url 'flag_note' note.id %}"
- var edit_note_tags_url = "{% url 'edit_note_tags' note.id %}"
- var note_downloaded_url = "{% url 'downloaded_note' note.id %}"
- var note_contents_url = "{{ S3_URL }}{{ note.get_relative_s3_path }}"
- var pdfControls = {% if pdf_controls %} true {% else %} false {% endif %};
- var csrf_token = "{{ csrf_token }}";
- var annotator_js_url = "{{ STATIC_URL }}js/annotator-full.min.js";
- var annotator_css_url = "{{ STATIC_URL }}css/annotator.min.css";
- var setup_ajax_url = "{{ STATIC_URL }}js/setup-ajax.js";
- var note_edit_url = "{% url 'edit_note' note.id %}";
- var user_authenticated = {% if user.is_authenticated %}true{% else %}false{% endif %};
- </script>
- {% compress js %}
- <script src="{{ STATIC_URL }}js/setup-ajax.js"></script>
- <script src="{{ STATIC_URL }}js/note-detail.js" ></script>
- <script src="{{ STATIC_URL }}js/pxem.jQuery.js"></script>
- <script src="{{ STATIC_URL }}js/marked.js" ></script>
- <script src="{{ STATIC_URL }}js/annotator-full.min.js"></script>
- {% endcompress %}
- <script>
- {% if show_note_container %}
- $(function() {
- $(document).foundation('joyride', 'start');
- initNoteContentPage();
- });
- {% endif %}
-
- {% if show_keywords %}
- $(function() {
- initNoteKeywordsPage();
- });
- {% endif %}
- </script>
-{% endblock %}
-
-{% block raw_content %}
- <section id="note_content">
-
- <div class="return-to-course show-for-large-up">
- <div class="row">
- <div class="small-12 columns">
- <a href="{{ note.course.get_absolute_url }}" class="inherit-color">
- <i class="fa fa-angle-double-left"></i> See all notes for {{ note.course.name }}
- </a>
- </div>
- </div>
- </div>
-
- <div id="note_header">
-
- <div class="row header-byline">
- <div class="small-12 columns">
- <strong>Lecture note for {{ note.course.name }} </strong>
- at
- {% if note.course.department.school %}
- {{ note.course.department.school.name }}
- {% else %}
- {{ note.course.school.name }}
- {% endif %}
-
- <span style="display: inline;"><span class="show-for-large-up"><i class="fa fa-thumbs-up"></i> <span id="thank-number">{{ note.thanks }}</span> Thank{{ note.thanks|pluralize }}</span></span>
- </div>
- </div>
-
- <div class="row museo700">
- <div class="small-12 columns header-title-row">
- <span class="header-title">{{ note.name }} </span>
- <span style="display: inline;">
- <span class="show-for-large-up">
- {% if user.is_authenticated %}
- {% if already_thanked %}
- <button id="thank-button-disabled" class="modify-button disabled opentip"
- data-ot="You've already thanked this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-thumbs-up"></i> Thank Note</button>
- {% else %}
- <button id="thank-button" class="modify-button"><i class="fa fa-thumbs-up"></i> Thank Note</button>
- <button id="thank-button-disabled" class="modify-button disabled opentip hide"
- data-ot="You've already thanked this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-thumbs-up"></i> Thank Note</button>
- {% endif %}
- {% else %}
- <button id="thank-button-disabled" class="modify-button disabled opentip"
- data-ot="Log in to thank this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-thumbs-up"></i> Thank Note</button>
- {% endif %}
-
- {% if user.is_authenticated %}
- {% if already_flagged %}
- <button id="flag-button-disabled" class="modify-button disabled opentip"
- data-ot="You've already reported this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-flag"></i> Report Note</button>
- {% else %}
- <button id="flag-button" class="modify-button"><i class="fa fa-flag"></i> Report Note</button>
- <button id="flag-button-disabled" class="modify-button disabled opentip hide"
- data-ot="You've already reported this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-flag"></i> Report Note</button>
- {% endif %}
- {% else %}
- <button id="flag-button-disabled" class="modify-button disabled opentip"
- data-ot="Log in to report this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-flag"></i> Report Note</button>
- {% endif %}
-
- {% if user.is_authenticated %}
- <a href="{{ note.get_fp_url }}">
- <button id="note-download-button" class="modify-button opentip"
- data-ot="It costs 2 karma points to download a note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-download"></i> Download Note</button></a>
- {% else %}
- <button id="note-download-button-disabled" class="modify-button disabled opentip"
- data-ot="Log in to download this note"
- {% include 'partial/opentip_settings.html' %}>
- <i class="fa fa-download"></i> Download Note</button>
- {% endif %}
-
- {% if user.get_profile.can_edit_items and note.user != user %}
- <button id="edit-note-tags" class="modify-button" data-reveal-id="note-tag-dialog">
- <i class="fa fa-pencil-square-o"></i> Edit Tags
- </button>
- {% endif %}
-
- {% if note.user == request.user %}
- <button id="edit-button" data-reveal-id="note-edit-dialog" class="modify-button"> <i class="fa fa-edit"></i> Edit This Note</button>
- {% endif %}
-
- {% if note.license %}
- {{ note.license.html|safe }} {% if note.upstream_link %}<a href="{{ note.upstream_link }}" target="_blank">{{ note.upstream_link|slice:":80" }}</a>{% endif %}
- {% endif %}
- </span>
- </span>
- </div>
- </div>
-
- {% if note.category %}
- <div id="note-category" class="row show-for-large-up">
- <div class="small-12 columns">
- <em>{{ note.get_category_display }}</em>
- </div>
+<div id="note_container" class="">
+ {% if pdf_controls %}
+ <div id="zoom-buttons" class="row show-for-medium-up">
+ <div id="outline-btn-wrapper" class="small-1 columns hide show-for-medium-up">
+ <i id="outline-btn" class="zoom-button fa fa-bars fa-2x"></i>
</div>
- {% endif %}
-
- <div id="note-tags" class="row show-for-large-up">
- <div class="small-12 columns">
- <strong>Tags: </strong>
- <span class="tags">
- {% if note.tags.all %}
- {% for tag in note.tags.all %}
- <span class="tag-span">
- {{ tag.name }}{% if not forloop.last %}, {% endif %}
- </span>
- {% endfor %}
- {% else %}
- <em class="light">(none defined yet)</em>
- {% endif %}
- </span>
- </div><!-- /note_tags -->
+ <div class="small-4 columns">
+ <span>Jump to page:
+ <input id="scroll-to" type="text" style="width: 3em; display: inline" /></span>
</div>
-
- <div id="note-tag-dialog" class="reveal-modal" data-reveal>
- <a class="close-reveal-modal">×</a>
- <div class="row">
- <div class="small-12 columns">
- <h3>Edit this note's tags</h3>
- <input id="note_tags_input" type="text" value="{% for tag in note.tags.all %}{{ tag.name }}{% if not forloop.last %}, {% endif %}{% endfor %}">
- <button id="save_note_tags" type="submit" value="tags-form"><i class="fa fa-save"></i> Save</button>
- </div>
- </div>
- </div>
-
- <div id="note-edit-dialog" class="reveal-modal" data-reveal>
- <a class="close-reveal-modal">×</a>
- <div class="row">
- <div class="small-8 columns">
- <h3>Edit Your Note</h3>
- </div>
- <div class="small-4 columns text-right">
- <form method="POST" action="{% url 'note_delete' %}">
- {% csrf_token %}
- {{ note_delete_form }}
- <button id="delete-note-button" type="submit" class="scary"><i class="fa fa-trash-o"></i> Delete Note</button>
- </form>
- </div>
- </div>
- <div class="row">
- <form method="POST" action="{{ note.get_absolute_url }}">
- {% csrf_token %}
- <div class="small-12 large-6 columns">
- {% with note_edit_form.name as field %}
- {{ field.errors|safe }}
- <label for="{{ field.id_for_label }}">{{ field.label }}:</label>
- {{ field }}
- <p>{{ field.help_text }}</p>
- {% endwith %}
- </div>
- <div class="small-12 large-6 columns">
- {% with note_edit_form.tags as field %}
- {{ field.errors|safe }}
- <label for="{{ field.id_for_label }}">{{ field.label }}:</label>
- {{ field }}
- <p>{{ field.help_text }}</p>
- {% endwith %}
- </div>
- <div class="small-12 columns text-center">
- <button type="submit"><i class="fa fa-save"></i> Save</button>
- </div>
- </form>
- </div>
- </div>
-
- </div><!-- /note header -->
-
- <div class="row">
- <div id="tabs" class="small-12 columns">
- <dl class="tabs">
- <dd id="note-tab-button" class="{% if show_note_container %}active{% endif %}">
- <a href="{{ note.get_absolute_url }}">Note</a>
- </dd>
- <dd id="keywords-tab-button" class="{% if show_keywords %}active{% endif %}">
- <a href="{{ note.get_absolute_keywords_url }}">Key Terms & Definitions</a>
- </dd>
- </dl>
- <div class="tabs-content">
- </div>
- {% if show_note_container %}
- <div id="note_container" class="">
- {% if pdf_controls %}
- <div id="zoom-buttons" class="row show-for-medium-up">
- <div id="outline-btn-wrapper" class="small-1 columns hide show-for-medium-up">
- <i id="outline-btn" class="zoom-button fa fa-bars fa-2x"></i>
- </div>
- <div class="small-4 columns">
- <span>Jump to page:
- <input id="scroll-to" type="text" style="width: 3em; display: inline" /></span>
- </div>
- <div class="small-2 small-centered columns center">
- <i id="minus-btn" class="zoom-button fa fa-search-minus fa-2x"></i>
- <i id="plus-btn" class="zoom-button fa fa-search-plus fa-2x"></i>
- </div>
- </div>
- {% endif %}
-
- <div class="row">
- <div class="small-12 small-centered columns medium-12 large-12 body_copy">
- <div id="note-content-wrapper" class="note-text">
- {% if note.has_markdown %}
- <span id="note-markdown" data-markdown="{{note.notemarkdown.markdown}}"></span>
- {% else %}
- <iframe style="border:none; width:100%; min-height: 1000px;"
- id="noteframe"></iframe>
- <noscript>
- {{ note.text }}
- </noscript>
- {% endif %}
- </div> <!-- .note-text -->
- </div><!-- /body_copy -->
- </div>
- </div><!-- /note_container -->
- {% endif %}
- {% if show_keywords %}
- <div id="keywords" class="content">
- <div class="row">
- <div class="small-12 columns">
- {% if user.is_authenticated %}
- <p id="keyword-intro">These key terms and definitions have been defined by KarmaNotes users.
- You can edit them for accuracy and add more if you like.</p>
- <p><button id="edit-keywords-button" class="museo700"><i class="fa fa-edit"></i> Edit Key Terms & Definitions</button></p>
- {% else %}
- <p id="keyword-intro">These key terms and definitions have been defined by KarmaNotes users.</p>
- {% endif %}
- <table id="keywords-data-table">
- <thead>
- <tr>
- <td>Key Terms</td>
- <td>Definitions</td>
- </tr>
- </thead>
- {% for keyword in keywords %}
- <tr>
- <td>{{ keyword.word }}</td>
- <td>
- {% if keyword.definition %}
- {{ keyword.definition }}
- {% else %}
- <em class="light">(not defined yet)</em>
- {% endif %}
- </td>
- </tr>
- {% endfor %}
- </table>
-
- <form id="keyword-form" action="{{ note.get_absolute_keywords_url }}" method="post" class="hide">
- {% csrf_token %}
- {{ keyword_formset.management_form }}
- <div class="hide" id="keyword-form-prototype">
- <div class="row keyword-form-row">
- <div class="small-12 large-4 columns">
- {{ keyword_prototype_form.keyword }}
- </div>
- <div class="small-12 large-8 columns">
- {{ keyword_prototype_form.definition }}
- {{ keyword_prototype_form.id }}
- </div>
- </div>
- <hr class="hide-for-large-up" />
- </div>
- <div id="keyword-form-rows">
- {% for form_row in keyword_formset %}
- <div class="row keyword-form-row" data-index="{{ forloop.counter0 }}">
- <div class="small-12 large-4 columns">
- {{ form_row.keyword }}
- </div>
- <div class="small-12 large-8 columns">
- {{ form_row.definition }}
- {{ form_row.id }}
- </div>
- </div>
- <hr class="hide-for-large-up" />
- {% endfor %}
- </div>
- <div class="row hide-for-medium-down">
- <div class="small-12 columns">
- <p class="keywords-hint">(Click <i class="fa fa-plus"></i> or press TAB in the last definition for another row)</p>
- </div>
- </div>
- <div class="row">
- <div class="small-2 columns">
- <button type="submit" name="action" value="keyword-form">Save</button>
- </div>
- <div class="small-9 large-10 columns center">
- <i id="add-row-btn" class="fa fa-plus fa-2x"></i>
- </div>
- </div>
- </form>
- </div>
- </div>
- </div> <!-- keywords -->
- {% endif %}
+ <div class="small-2 small-centered columns center">
+ <i id="minus-btn" class="zoom-button fa fa-search-minus fa-2x"></i>
+ <i id="plus-btn" class="zoom-button fa fa-search-plus fa-2x"></i>
</div>
</div>
-
- </section><!--/note_content-->
-
- <ol class="joyride-list" data-joyride
- data-options="cookie_monster: true; cookie_name: note_detail_joyride">
- <li data-id="note-content-wrapper" data-text="Awesome!" data-options="tip_location: top">
- <p>You can highlight important words or phrases in this note to add definitions for them.</p>
- </li>
- <li data-id="keywords-tab-button" data-text="Awesome!" data-options="tip_location: top">
- <p>Keywords you define will appear here, and you can define new ones here too.</p>
- </li>
- </ol>
-
-{% endblock %}
-
-
+ {% endif %}
+
+ <div class="row">
+ <div class="small-12 small-centered columns medium-12 large-12 body_copy">
+ <div id="note-content-wrapper" class="note-text">
+ {% if note.has_markdown %}
+ <span id="note-markdown" data-markdown="{{note.notemarkdown.markdown}}"></span>
+ {% else %}
+ <iframe style="border:none; width:100%; min-height: 1000px;"
+ id="noteframe"></iframe>
+ <noscript>
+ {{ note.text }}
+ </noscript>
+ {% endif %}
+ </div> <!-- .note-text -->
+ </div><!-- /body_copy -->
+ </div>
+</div><!-- /note_container -->
\ No newline at end of file
--- /dev/null
+
+<div id="keywords" class="content">
+ <div class="row">
+ <div class="small-12 columns">
+ {% if user.is_authenticated %}
+ <p id="keyword-intro">These key terms and definitions have been defined by KarmaNotes users.
+ You can edit them for accuracy and add more if you like.</p>
+ <p><button id="edit-keywords-button" class="museo700"><i class="fa fa-edit"></i> Edit Key Terms & Definitions</button></p>
+ {% else %}
+ <p id="keyword-intro">These key terms and definitions have been defined by KarmaNotes users.</p>
+ {% endif %}
+ <table id="keywords-data-table">
+ <thead>
+ <tr>
+ <td>Key Terms</td>
+ <td>Definitions</td>
+ </tr>
+ </thead>
+ {% for keyword in keywords %}
+ <tr>
+ <td>{{ keyword.word }}</td>
+ <td>
+ {% if keyword.definition %}
+ {{ keyword.definition }}
+ {% else %}
+ <em class="light">(not defined yet)</em>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+
+ <form id="keyword-form" action="{{ note.get_absolute_keywords_url }}" method="post" class="hide">
+ {% csrf_token %}
+ {{ keyword_formset.management_form }}
+ <div class="hide" id="keyword-form-prototype">
+ <div class="row keyword-form-row">
+ <div class="small-12 large-4 columns">
+ {{ keyword_prototype_form.keyword }}
+ </div>
+ <div class="small-12 large-8 columns">
+ {{ keyword_prototype_form.definition }}
+ {{ keyword_prototype_form.id }}
+ </div>
+ </div>
+ <hr class="hide-for-large-up" />
+ </div>
+ <div id="keyword-form-rows">
+ {% for form_row in keyword_formset %}
+ <div class="row keyword-form-row" data-index="{{ forloop.counter0 }}">
+ <div class="small-12 large-4 columns">
+ {{ form_row.keyword }}
+ </div>
+ <div class="small-12 large-8 columns">
+ {{ form_row.definition }}
+ {{ form_row.id }}
+ </div>
+ </div>
+ <hr class="hide-for-large-up" />
+ {% endfor %}
+ </div>
+ <div class="row hide-for-medium-down">
+ <div class="small-12 columns">
+ <p class="keywords-hint">(Click <i class="fa fa-plus"></i> or press TAB in the last definition for another row)</p>
+ </div>
+ </div>
+ <div class="row">
+ <div class="small-2 columns">
+ <button type="submit" name="action" value="keyword-form">Save</button>
+ </div>
+ <div class="small-9 large-10 columns center">
+ <i id="add-row-btn" class="fa fa-plus fa-2x"></i>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+</div> <!-- keywords -->
--- /dev/null
+<div id="quiz" class="content">
+ <div class="row">
+ <div class="small-12 columns">
+ <div id="quiz-intro">
+ {% if questions %}
+ These quiz questions have been randomly generated from the keywords and definitions associated
+ with this note. Refresh to get different questions.
+ {% else %}
+ No keywords with definitions have been supplied, so we can't generate any quiz questions.
+ Provide some key terms with their definitions, and we'll create questions based on them.
+ {% endif %}
+ </div>
+ </div>
+ </div>
+
+ {% for question in questions %}
+ <div class="quiz-question-wrapper">
+ <div class="row">
+ <div class="small-12 columns correct-label hide">
+ <div class="correct-label-inner">Correct</div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="small-12 columns incorrect-label hide">
+ <div class="incorrect-label-inner">Incorrect</div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="small-12 columns quiz-question">
+ <div class="quiz-question-inner">
+ <div class="question-text"><strong>{{ forloop.counter }}. {{ question.question_text }}</strong></div>
+ {% if question.question_type == 'MultipleChoiceQuestion' %}
+ {% for choice in question.choices %}
+ <div class="question-choices">
+ <input type="radio"
+ name="group_{{ forloop.parentloop.counter0 }}"
+ id="choice_{{ forloop.parentloop.counter0 }}_{{ forloop.counter0 }}"
+ value="choice_{{ forloop.parentloop.counter0 }}_{{ forloop.counter0 }}"
+ data-correct="{% if choice.correct %}true{% else %}false{% endif %}" />
+ <label for="choice_{{ forloop.parentloop.counter0 }}_{{ forloop.counter0 }}">{{ choice.text }}</label>
+ </div>
+ {% endfor %}
+ {% endif %}
+ {% if question.question_type == 'TrueFalseQuestion' %}
+ <div class="question-choices">
+ <input type="radio"
+ name="group_{{ forloop.counter0 }}"
+ id="choice_{{ forloop.counter0 }}_true"
+ value="choice_{{ forloop.counter0 }}_true"
+ data-correct="{% if question.true %}true{% else %}false{% endif %}" />
+ <label for="choice_{{ forloop.counter0 }}_true">True</label>
+ </div>
+ <div class="question-choices">
+ <input type="radio"
+ name="group_{{ forloop.counter0 }}"
+ id="choice_{{ forloop.counter0 }}_false"
+ value="choice_{{ forloop.counter0 }}_false"
+ data-correct="{% if question.false %}true{% else %}false{% endif %}" />
+ <label for="choice_{{ forloop.counter0 }}_false">False</label>
+ </div>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ </div>
+ {% endfor %}
+
+ <div class="row">
+ <div class="small-12 columns">
+ <button id="check-answers-button">Check Answers</button>
+ </div>
+ </div>
+
+</div>
\ No newline at end of file
from karmaworld.apps.courses.views import school_course_list
from karmaworld.apps.courses.views import school_course_instructor_list
from karmaworld.apps.notes.views import NoteView, thank_note, NoteSearchView, flag_note, downloaded_note, edit_note_tags, \
- NoteKeywordsView, edit_note, NoteDeleteView
+ NoteKeywordsView, NoteQuizView, edit_note, NoteDeleteView
from karmaworld.apps.moderation import moderator
from karmaworld.apps.document_upload.views import save_fp_upload
from karmaworld.apps.quizzes.views import set_delete_keyword_annotator, get_keywords_annotator
NoteView.as_view(), name='note_detail'),
url(r'^note/' + SLUG.format('school_') + '/' + SLUG.format('course_') +'/'+ SLUG.format('') +'/keywords/$',
NoteKeywordsView.as_view(), name='note_keywords'),
+ url(r'^note/' + SLUG.format('school_') + '/' + SLUG.format('course_') +'/'+ SLUG.format('') +'/quiz/$',
+ NoteQuizView.as_view(), name='note_quiz'),
url(r'note/delete/$', NoteDeleteView.as_view(), name='note_delete'),
django-ajax-selects
git+https://github.com/btbonval/django-ajax-selects-cascade.git
psycopg2
-git+https://github.com/Soaa-/django-nested-inlines.git
pyth
-http://python-graph.googlecode.com/files/python-graph-core-1.8.2.tar.gz
-nltk
-numpy