Commit 19356ffd by Piotr Mitros Committed by David Baumgold

Puts course listings in a sane order

parent 83c54d4e
""" """
Student Views Student Views
""" """
import datetime
import logging import logging
import re import re
import uuid import uuid
import time import time
import json import json
from collections import defaultdict from collections import defaultdict
from datetime import datetime
from pytz import UTC from pytz import UTC
from django.conf import settings from django.conf import settings
...@@ -42,6 +42,7 @@ from edxmako.shortcuts import render_to_response, render_to_string ...@@ -42,6 +42,7 @@ from edxmako.shortcuts import render_to_response, render_to_string
from mako.exceptions import TopLevelLookupException from mako.exceptions import TopLevelLookupException
from course_modes.models import CourseMode from course_modes.models import CourseMode
from student.models import ( from student.models import (
Registration, UserProfile, PendingNameChange, Registration, UserProfile, PendingNameChange,
PendingEmailChange, CourseEnrollment, unique_id_for_user, PendingEmailChange, CourseEnrollment, unique_id_for_user,
...@@ -64,6 +65,7 @@ from collections import namedtuple ...@@ -64,6 +65,7 @@ from collections import namedtuple
from courseware.courses import get_courses, sort_by_announcement from courseware.courses import get_courses, sort_by_announcement
from courseware.access import has_access from courseware.access import has_access
from courseware.models import course_modified_times
from django_comment_common.models import Role from django_comment_common.models import Role
...@@ -226,7 +228,7 @@ def single_course_reverification_info(user, course, enrollment): # pylint: disa ...@@ -226,7 +228,7 @@ def single_course_reverification_info(user, course, enrollment): # pylint: disa
ReverifyInfo: (course_id, course_name, course_number, date, status) ReverifyInfo: (course_id, course_name, course_number, date, status)
OR, None: None if there is no re-verification info for this enrollment OR, None: None if there is no re-verification info for this enrollment
""" """
window = MidcourseReverificationWindow.get_window(course.id, datetime.datetime.now(UTC)) window = MidcourseReverificationWindow.get_window(course.id, datetime.now(UTC))
# If there's no window OR the user is not verified, we don't get reverification info # If there's no window OR the user is not verified, we don't get reverification info
if (not window) or (enrollment.mode != "verified"): if (not window) or (enrollment.mode != "verified"):
...@@ -244,6 +246,8 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set): ...@@ -244,6 +246,8 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set):
Get the relevant set of (Course, CourseEnrollment) pairs to be displayed on Get the relevant set of (Course, CourseEnrollment) pairs to be displayed on
a student's dashboard. a student's dashboard.
""" """
pairs = []
for enrollment in CourseEnrollment.enrollments_for_user(user): for enrollment in CourseEnrollment.enrollments_for_user(user):
course = modulestore().get_course(enrollment.course_id) course = modulestore().get_course(enrollment.course_id)
if course and not isinstance(course, ErrorDescriptor): if course and not isinstance(course, ErrorDescriptor):
...@@ -257,12 +261,18 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set): ...@@ -257,12 +261,18 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set):
elif course.location.org in org_filter_out_set: elif course.location.org in org_filter_out_set:
continue continue
yield (course, enrollment) pairs.append((course, enrollment))
else: else:
log.error("User {0} enrolled in {2} course {1}".format( log.error("User {0} enrolled in {2} course {1}".format(
user.username, enrollment.course_id, "broken" if course else "non-existent" user.username, enrollment.course_id, "broken" if course else "non-existent"
)) ))
## Sort pairs in order of courseware access. If I am actively using a course, it should bubble up to the top.
modified_times_map = course_modified_times(user, [p[0].scope_ids.usage_id for p in pairs])
def key_function(x):
return modified_times_map.get(unicode(x[0].scope_ids.usage_id), datetime.min)
pairs.sort(key=key_function, reverse=True)
return pairs
def _cert_info(user, course, cert_status): def _cert_info(user, course, cert_status):
""" """
...@@ -429,7 +439,7 @@ def complete_course_mode_info(course_id, enrollment): ...@@ -429,7 +439,7 @@ def complete_course_mode_info(course_id, enrollment):
mode_info['show_upsell'] = True mode_info['show_upsell'] = True
# if there is an expiration date, find out how long from now it is # if there is an expiration date, find out how long from now it is
if modes['verified'].expiration_datetime: if modes['verified'].expiration_datetime:
today = datetime.datetime.now(UTC).date() today = datetime.now(UTC).date()
mode_info['days_for_upsell'] = (modes['verified'].expiration_datetime.date() - today).days mode_info['days_for_upsell'] = (modes['verified'].expiration_datetime.date() - today).days
return mode_info return mode_info
...@@ -1167,7 +1177,7 @@ def disable_account_ajax(request): ...@@ -1167,7 +1177,7 @@ def disable_account_ajax(request):
context['message'] = _("Unexpected account status") context['message'] = _("Unexpected account status")
return JsonResponse(context, status=400) return JsonResponse(context, status=400)
user_account.changed_by = request.user user_account.changed_by = request.user
user_account.standing_last_changed_at = datetime.datetime.now(UTC) user_account.standing_last_changed_at = datetime.now(UTC)
user_account.save() user_account.save()
return JsonResponse(context) return JsonResponse(context)
...@@ -1552,7 +1562,7 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many ...@@ -1552,7 +1562,7 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many
if do_external_auth: if do_external_auth:
eamap.user = new_user eamap.user = new_user
eamap.dtsignup = datetime.datetime.now(UTC) eamap.dtsignup = datetime.now(UTC)
eamap.save() eamap.save()
AUDIT_LOG.info("User registered with external_auth %s", post_vars['username']) AUDIT_LOG.info("User registered with external_auth %s", post_vars['username'])
AUDIT_LOG.info('Updated ExternalAuthMap for %s to be %s', post_vars['username'], eamap) AUDIT_LOG.info('Updated ExternalAuthMap for %s to be %s', post_vars['username'], eamap)
...@@ -1980,7 +1990,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument ...@@ -1980,7 +1990,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument
meta = u_prof.get_meta() meta = u_prof.get_meta()
if 'old_emails' not in meta: if 'old_emails' not in meta:
meta['old_emails'] = [] meta['old_emails'] = []
meta['old_emails'].append([user.email, datetime.datetime.now(UTC).isoformat()]) meta['old_emails'].append([user.email, datetime.now(UTC).isoformat()])
u_prof.set_meta(meta) u_prof.set_meta(meta)
u_prof.save() u_prof.save()
# Send it to the old email... # Send it to the old email...
...@@ -2100,7 +2110,7 @@ def accept_name_change_by_id(uid): ...@@ -2100,7 +2110,7 @@ def accept_name_change_by_id(uid):
meta = u_prof.get_meta() meta = u_prof.get_meta()
if 'old_names' not in meta: if 'old_names' not in meta:
meta['old_names'] = [] meta['old_names'] = []
meta['old_names'].append([u_prof.name, pnc.rationale, datetime.datetime.now(UTC).isoformat()]) meta['old_names'].append([u_prof.name, pnc.rationale, datetime.now(UTC).isoformat()])
u_prof.set_meta(meta) u_prof.set_meta(meta)
u_prof.name = pnc.new_name u_prof.name = pnc.new_name
......
...@@ -93,6 +93,12 @@ class StudentModule(models.Model): ...@@ -93,6 +93,12 @@ class StudentModule(models.Model):
return unicode(repr(self)) return unicode(repr(self))
def course_modified_times(user, ids):
''' Returns the times when a given studentmodule was last modified.
'''
results = StudentModule.objects.filter(student=user, module_state_key__in=ids).values_list('module_state_key', 'modified')
return dict(results)
class StudentModuleHistory(models.Model): class StudentModuleHistory(models.Model):
"""Keeps a complete history of state changes for a given XModule for a given """Keeps a complete history of state changes for a given XModule for a given
Student. Right now, we restrict this to problems so that the table doesn't Student. Right now, we restrict this to problems so that the table doesn't
......
...@@ -291,7 +291,7 @@ ...@@ -291,7 +291,7 @@
<section class="my-courses" id="my-courses"> <section class="my-courses" id="my-courses">
<header> <header>
<h2>${_("Current Courses")}</h2> <div style="display:flex"><h2>${_("Courses")} </h2><div style="flex-grow:1"></div><div style="font-size: 13px; color: #646464;">${_("ordered by recent activity")}</div></div>
</header> </header>
% if len(course_enrollment_pairs) > 0: % if len(course_enrollment_pairs) > 0:
......
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