Skip to content

Commit

Permalink
Merge branch 'develop' into central-develop
Browse files Browse the repository at this point in the history
Conflicts:
	kalite/contentload/management/commands/generate_assessment_zips.py
	kalite/distributed/tests/browser_tests/quiz.py
	static-libraries/js/khan-lite.js
  • Loading branch information
aronasorman committed Mar 20, 2015
2 parents 645c7f0 + 4905929 commit 1648ace
Show file tree
Hide file tree
Showing 83 changed files with 1,013 additions and 1,062 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ writeup/
/kalite/kalite-*.zip
/kalite/local_settings.py
/kalite/media
/kalite/temp
/data/*
!/data/khan/
/data/khan/assessmentitems.json
Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Please include the following information when opening an issue:
* Steps to reproduce (be detailed!)

If opening a PR, please observe the following guidelines
* If you're fixing a bug, write a regression test (or have a really good reason for not writing one... and I mean **really** good!)
* If you're fixing a bug, write a regression test (or have a really good reason for not writing one... and I mean **really** good!). Additionally, add in a "Fixes `issue number`" for PRs that address a certain issue (e.g. "Fixes #3390").
* If your PR changes or adds to the User Interface, please include screenshots in either the description or the comments.
* Give a brief summary of your changes in the PR description. Add in any other notes that are important for the reviewer to know.
* Update the documentation if your changes affect it (don't just assume they don't)
* Double check your own code for good style
2 changes: 1 addition & 1 deletion data/khan/exercises.json

Large diffs are not rendered by default.

Binary file added data/khan/images/logo_10_enlarged_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions data/khan/topic_hierarchy.json
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@
{
"description": "Equality is usually a good thing, but the world is not a perfect place. No matter how hard we try, we can't help but compare one thing to another and realize how unequal they may be.\n\nThis tutorial gives you the tools to do these comparisons in the mathematical world (which we call inequalities). You'll become familiar with the \"greater than\" and \"less than symbols\" and learn to use them.",
"id": "greater-than-less-than",
"title": "Inequalties : Greater than and less than basics"
"title": "Inequalities : Greater than and less than basics"
},
{
"description": "You've probably been learning how to do arithmetic for some time and feel pretty good about it. This tutorial will make you feel even better once by showing you a bunch of examples of where it can be applied (using multiple skills at a time). Get through the exercises here and you really are an arithmetic rock star!",
Expand Down Expand Up @@ -7158,7 +7158,7 @@
"title": "AP Art History"
}
],
"description": " ",
"description": "",
"id": "test-prep",
"title": "Test prep"
},
Expand Down Expand Up @@ -7639,4 +7639,4 @@
"description": "",
"id": "root",
"title": "Khan Academy"
}
}
2 changes: 1 addition & 1 deletion data/khan/topics.json
100755 → 100644

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion kalite/basetests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ class PathsTests(DependenciesTests):
Check that we have access to all paths and files we need read or write access to.
"""

JSON_FILES = ("assessmentitems.json", "channel_data.json", "contents.json", "exercises.json",
JSON_FILES = ("channel_data.json", "contents.json", "exercises.json",
"topic_hierarchy.json", "topics.json",)

def test_content_path(self):
Expand Down
8 changes: 5 additions & 3 deletions kalite/coachreports/api_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ def dehydrate(self, bundle):
return bundle

def get_object_list(self, request):
#TODO-BLOCKER(66eli77): need to find a way to include exercises that are not completed yet.
#TODO(66eli77): need to find a way to include exercises that are not completed yet.
#TODO(MCGallaspy): Probably by adding an "attempted_timestamp" field to the ExerciseLog model
if not request.GET.get('facility_id'):
if not request.GET.get('group_id'):
return super(ExerciseSummaryResource, self).get_object_list(request).filter(
Expand Down Expand Up @@ -236,7 +237,8 @@ def dehydrate(self, bundle):
return bundle

def get_object_list(self, request):
#TODO-BLOCKER(66eli77): need to find a way to include exercises that are not completed yet.
#TODO(66eli77): need to find a way to include exercises that are not completed yet.
#TODO(MCGallaspy): Probably by adding an "attempted_timestamp" field to the ExerciseLog model
if not request.GET.get('facility_id'):
if not request.GET.get('group_id'):
return super(ExerciseSummaryResource, self).get_object_list(request).filter(
Expand Down Expand Up @@ -292,4 +294,4 @@ def obj_get_list(self, bundle, **kwargs):
self.user_info.append(user_dic)

self.user_info.reverse()
return filtered_logs
return filtered_logs
5 changes: 2 additions & 3 deletions kalite/coachreports/tests/coachreport_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

from datetime import datetime, timedelta
from django.utils import unittest
from selenium.webdriver.common.by import By
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

from kalite.main.models import AttemptLog
from kalite.testing.base import KALiteBrowserTestCase, KALiteTestCase
from kalite.testing.mixins import BrowserActionMixins, CreateAdminMixin, CreatePlaylistProgressMixin, CreateZoneMixin, \
FacilityMixins, StudentProgressMixin, StoreMixins
FacilityMixins, StudentProgressMixin


class APIDropdownTests(FacilityMixins,
Expand Down Expand Up @@ -402,7 +402,6 @@ def test_student_playlist_progress(self):
@unittest.skipUnless("nalanda" in settings.CONFIG_PACKAGE, "requires Nalanda")
class SpendingReportTests(FacilityMixins,
CreateAdminMixin,
StoreMixins,
BrowserActionMixins,
KALiteBrowserTestCase):

Expand Down
79 changes: 14 additions & 65 deletions kalite/coachreports/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from django.conf import settings; logging = settings.LOG
from django.contrib import messages
from django.contrib.messages import ERROR
from django.contrib.messages import WARNING
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.db.models import Q
Expand All @@ -16,6 +16,8 @@
from .api_views import get_data_form, stats_dict
from django.shortcuts import get_object_or_404

from kalite.facility import get_accessible_objects_from_logged_in_user
from kalite.control_panel import api_resources as control_panel_api_resources
from kalite.distributed.api_views import compute_total_points
from kalite.facility.decorators import facility_required
from kalite.facility.models import Facility, FacilityUser, FacilityGroup
Expand All @@ -31,55 +33,6 @@
# shared by test_view and test_detail view
SUMMARY_STATS = [ugettext_lazy('Max'), ugettext_lazy('Min'), ugettext_lazy('Average'), ugettext_lazy('Std Dev')]


def get_accessible_objects_from_logged_in_user(request, facility):
"""Given a request, get all the facility/group/user objects relevant to the request,
subject to the permissions of the user type.
Make sure the returned `facilities` object is always a Facility queryset or an empty list.
"""

# Options to select. Note that this depends on the user.
facilities = []
if request.user.is_superuser:
facilities = Facility.objects.all()
# Groups is now a list of objects with a key for facility id, and a key
# for the list of groups at that facility.
# TODO: Make this more efficient.
groups = [{"facility": f.id, "groups": FacilityGroup.objects.filter(facility=f)} for f in facilities]

elif "facility_user" in request.session:
user = request.session["facility_user"]
if user.is_teacher:
facilities = Facility.objects.all()
groups = [{"facility": f.id, "groups": FacilityGroup.objects.filter(facility=f)} for f in facilities]
else:
# Students can only access their group
if facility and isinstance(facility, Facility):
facilities = Facility.objects.filter(id=facility.id)
if not user.group:
groups = []
else:
groups = [{"facility": user.facility.id,
"groups": FacilityGroup.objects.filter(id=request.session["facility_user"].group)}]
elif facility:
facilities = Facility.objects.filter(id=facility.id)
groups = [{"facility": facility.id, "groups": FacilityGroup.objects.filter(facility=facility)}]
else:
# defaults to all facilities and groups
facilities = Facility.objects.all()
groups = [{"facility": f.id, "groups": FacilityGroup.objects.filter(facility=f)} for f in facilities]

ungrouped_available = False
for f in facilities:
# Check if there is at least one facility with ungrouped students.
ungrouped_available = f.has_ungrouped_students
if ungrouped_available:
break

return (groups, facilities, ungrouped_available)


def plotting_metadata_context(request, facility=None, topic_path=[], *args, **kwargs):
"""Basic context for any plot: get the data form, a dictionary of stat definitions,
and the full gamut of facility/group objects relevant to the request."""
Expand Down Expand Up @@ -225,17 +178,16 @@ def tabular_view(request, report_type="exercise"):
# Exactly one of topic_id or playlist_id should be present
if not ((topic_id or playlist_id) and not (topic_id and playlist_id)):
if playlists:
messages.add_message(request, ERROR, _("Please select a playlist."))
messages.add_message(request, WARNING, _("Please select a playlist."))
elif topics:
messages.add_message(request, ERROR, _("Please select a topic."))
messages.add_message(request, WARNING, _("Please select a topic."))
return context

playlist = (filter(lambda p: p.id == playlist_id, Playlist.all()) or [None])[0]

if group_id:
# Narrow by group
from control_panel.api_resources import UNGROUPED_KEY
if group_id == UNGROUPED_KEY:
if group_id == control_panel_api_resources.UNGROUPED_KEY:
users = FacilityUser.objects.filter(group__isnull=True, is_teacher=False)
if facility:
# filter only those ungrouped students for the facility
Expand Down Expand Up @@ -344,22 +296,22 @@ def tabular_view(request, report_type="exercise"):
# 1. check group facility groups
if len(groups) > 0 and not groups[0]['groups']:
# 1. No groups available (for facility) and "no students" returned.
messages.add_message(request, ERROR,
messages.add_message(request, WARNING,
_("No learner accounts have been created for selected facility/group."))
elif topic_id and playlist_id:
# 2. Both topic and playlist are selected.
messages.add_message(request, ERROR, _("Please select either a topic or a playlist above, but not both."))
messages.add_message(request, WARNING, _("Please select either a topic or a playlist above, but not both."))
elif not topic_id and not playlist_id:
# 3. Group was selected, but data not queried because a topic or playlist was not selected.
if playlists:
# 4. No playlist was selected.
messages.add_message(request, ERROR, _("Please select a playlist."))
messages.add_message(request, WARNING, _("Please select a playlist."))
elif topics:
# 5. No topic was selected.
messages.add_message(request, ERROR, _("Please select a topic."))
messages.add_message(request, WARNING, _("Please select a topic."))
else:
# 6. Everything specified, but no users fit the query.
messages.add_message(request, ERROR, _("No learner accounts in this group have been created."))
messages.add_message(request, WARNING, _("No learner accounts in this group have been created."))
# End: Validate results by showing user messages.

log_coach_report_view(request)
Expand All @@ -378,11 +330,10 @@ def test_view(request):
# Get the TestLog objects generated by this group of students
# TODO(cpauya): what about queryset for ungrouped students?
test_logs = None
from control_panel.api_resources import UNGROUPED_KEY
if group_id:
test_logs = TestLog.objects.filter(user__group=group_id)
# Narrow all by ungroup facility user
if group_id == UNGROUPED_KEY:
if group_id == control_panel_api_resources.UNGROUPED_KEY:
test_logs = TestLog.objects.filter(user__group__isnull=True)
if facility:
TestLog.objects.filter(user__facility=facility, user__group__isnull=True)
Expand Down Expand Up @@ -501,11 +452,10 @@ def test_detail_view(request, test_id):

# get all of the test logs for this specific test object and generated by these specific users
if group_id:
from control_panel.api_resources import UNGROUPED_KEY
test_logs = TestLog.objects.filter(user__group=group_id, test=test_id)

# Narrow all by ungroup facility user
if group_id == UNGROUPED_KEY:
if group_id == control_panel_api_resources.UNGROUPED_KEY:
if facility:
test_logs = TestLog.objects.filter(user__group__isnull=True)
else:
Expand Down Expand Up @@ -644,13 +594,12 @@ def get_user_queryset(request, facility, group_id):
"""Return set of users appropriate to the facility and group"""
student_ordering = ["last_name", "first_name", "username"]
(groups, facilities, ungrouped_available) = get_accessible_objects_from_logged_in_user(request, facility=facility)
from control_panel.api_resources import UNGROUPED_KEY
if group_id:
# Narrow by group
users = FacilityUser.objects.filter(
group=group_id, is_teacher=False).order_by(*student_ordering)
# Narrow all by ungroup user
if group_id == UNGROUPED_KEY:
if group_id == control_panel_api_resources.UNGROUPED_KEY:
users = FacilityUser.objects.filter(group__isnull=True, is_teacher=False).order_by(*student_ordering)
if facility:
users = FacilityUser.objects.filter(facility=facility, group__isnull=True,
Expand Down
2 changes: 1 addition & 1 deletion kalite/contentload/management/commands/channels/khan.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
kind_blacklist = [None, "Separator", "CustomStack", "Scratchpad", "Article"]

slug_blacklist = ["new-and-noteworthy", "talks-and-interviews", "coach-res"] # not relevant
slug_blacklist += ["cs"] # not (yet) compatible
slug_blacklist += ["cs", "towers-of-hanoi"] # not (yet) compatible
slug_blacklist += ["cc-third-grade-math", "cc-fourth-grade-math", "cc-fifth-grade-math", "cc-sixth-grade-math", "cc-seventh-grade-math", "cc-eighth-grade-math"] # common core
slug_blacklist += ["MoMA", "getty-museum", "stanford-medicine", "crash-course1", "mit-k12", "hour-of-code", "metropolitan-museum", "bitcoin", "tate", "crash-course1", "crash-course-bio-ecology", "british-museum", "aspeninstitute", "asian-art-museum", "amnh"] # partner content

Expand Down
Loading

0 comments on commit 1648ace

Please sign in to comment.