diff --git a/common/djangoapps/entitlements/models.py b/common/djangoapps/entitlements/models.py index 3fea5e07b5..66ddec0231 100644 --- a/common/djangoapps/entitlements/models.py +++ b/common/djangoapps/entitlements/models.py @@ -257,3 +257,32 @@ class CourseEntitlement(TimeStampedModel): @classmethod def unexpired_entitlements_for_user(cls, user): return cls.objects.filter(user=user, expired_at=None).select_related('user') + + @classmethod + def get_entitlement_if_active(cls, user, course_uuid): + """ + Returns an entitlement for a given course uuid if an active entitlement exists, otherwise returns None. + An active entitlement is defined as an entitlement that has not yet expired or has a currently enrolled session. + """ + return cls.objects.filter( + user=user, + course_uuid=course_uuid + ).exclude(expired_at__isnull=False, enrollment_course_run=None).first() + + @classmethod + def get_active_entitlements_for_user(cls, user): + """ + Returns a list of active (enrolled or not yet expired) entitlements. + + Returns any entitlements that are: + 1) Not expired and no session selected + 2) Not expired and a session is selected + 3) Expired and a session is selected + + Does not return any entitlements that are: + 1) Expired and no session selected + """ + return cls.objects.filter(user=user).exclude( + expired_at__isnull=False, + enrollment_course_run=None + ).select_related('user').select_related('enrollment_course_run') diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index 933ce59cdd..c8266b9a0c 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -376,11 +376,15 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin): @patch.object(CourseOverview, 'get_from_id') def test_unfulfilled_expired_entitlement(self, mock_course_overview, mock_course_runs): """ - When a learner has an unfulfilled, expired entitlement, their course dashboard should have: - - a hidden 'View Course' button - - a message saying that they can no longer select a session + When a learner has an unfulfilled, expired entitlement, a card should NOT appear on the dashboard. + This use case represents either an entitlement that the user waited too long to fulfill, or an entitlement + for which they received a refund. """ - CourseEntitlementFactory(user=self.user, created=self.THREE_YEARS_AGO) + CourseEntitlementFactory( + user=self.user, + created=self.THREE_YEARS_AGO, + expired_at=datetime.datetime.now() + ) mock_course_overview.return_value = CourseOverviewFactory(start=self.TOMORROW) mock_course_runs.return_value = [ { @@ -391,9 +395,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin): } ] response = self.client.get(self.path) - self.assertIn('class="enter-course hidden"', response.content) - self.assertIn('You can no longer select a session', response.content) - self.assertNotIn('
', response.content) + self.assertEqual(response.content.count('
  • '), 0) @patch('student.views.get_course_runs_for_course') @patch.object(CourseOverview, 'get_from_id') diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 9fc071c837..5c07b4585d 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -698,7 +698,7 @@ def dashboard(request): course_enrollments = list(get_course_enrollments(user, site_org_whitelist, site_org_blacklist)) # Get the entitlements for the user and a mapping to all available sessions for that entitlement - course_entitlements = list(CourseEntitlement.objects.filter(user=user).select_related('enrollment_course_run')) + course_entitlements = list(CourseEntitlement.get_active_entitlements_for_user(user)) course_entitlement_available_sessions = {} for course_entitlement in course_entitlements: course_entitlement.update_expired_at() diff --git a/lms/static/js/spec/learner_dashboard/course_card_view_spec.js b/lms/static/js/spec/learner_dashboard/course_card_view_spec.js index 2fa0c250d3..0e44a48f88 100644 --- a/lms/static/js/spec/learner_dashboard/course_card_view_spec.js +++ b/lms/static/js/spec/learner_dashboard/course_card_view_spec.js @@ -234,16 +234,6 @@ define([ expect(view.$('.course-title-link').length).toEqual(0); }); - it('should show an unfulfilled expired user entitlement not allowing the changing of sessions', function() { - course.user_entitlement = { - uuid: '99fc7414c36d4f56b37e8e30acf4c7ba', - course_uuid: '99fc7414c36d4f56b37e8e30acf4c7ba', - expired_at: '2017-12-06 01:06:12', - expiration_date: '2017-12-05 01:06:12' - }; - setupView(course, false); - expect(view.$('.info-expires-at').text().trim()).toContain('You can no longer select a session. Your'); - }); it('should show an unfulfilled user entitlement allows you to select a session', function() { course.user_entitlement = { diff --git a/lms/static/sass/views/_program-details.scss b/lms/static/sass/views/_program-details.scss index cb0724d40f..654ab230cc 100644 --- a/lms/static/sass/views/_program-details.scss +++ b/lms/static/sass/views/_program-details.scss @@ -356,12 +356,16 @@ background-color: palette(primary, dark); height: 37px; width: 128px; - border-radius: 0; padding: 0; margin-bottom: 5px; margin-top: 7px; font-size: 0.9375em; + &:hover { + color: palette(primary, dark); + background-color: theme-color("inverse"); + } + /* IE11 CSS styles */ @media (min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { @include float(right); @@ -393,14 +397,7 @@ } .run-select { - @include margin-right(10px); - - width: 95%; - - @media (min-width: $bp-screen-sm) { - width: 300px; - } - + width: 100%; height: 34px; padding: 0; } @@ -511,7 +508,7 @@ .course-actions { @media (min-width: $bp-screen-md) { - width: 200px; + width: 100%; text-align: right; float: right; } diff --git a/lms/templates/dashboard/_dashboard_course_listing.html b/lms/templates/dashboard/_dashboard_course_listing.html index 939294c758..4e07740307 100644 --- a/lms/templates/dashboard/_dashboard_course_listing.html +++ b/lms/templates/dashboard/_dashboard_course_listing.html @@ -131,9 +131,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ % if is_unfulfilled_entitlement: - % if entitlement_expired_at: - ${_('You can no longer select a session, your final day to select a session was {entitlement_expired_at}.').format(entitlement_expired_at=entitlement_expired_at)} - % else: + % if not entitlement_expired_at: % if entitlement_expiration_date: ${_('You must select a session by {expiration_date} to access the course.').format(expiration_date=entitlement_expiration_date)} % else: @@ -156,7 +154,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ % if entitlement and not is_unfulfilled_entitlement and entitlement_expiration_date:
    - + % if entitlement_expired_at: ${_('You can no longer change sessions.')} % else: diff --git a/lms/templates/learner_dashboard/course_card.underscore b/lms/templates/learner_dashboard/course_card.underscore index 53f8d35469..3c238e95b2 100644 --- a/lms/templates/learner_dashboard/course_card.underscore +++ b/lms/templates/learner_dashboard/course_card.underscore @@ -25,9 +25,7 @@ <% if (user_entitlement && user_entitlement.expiration_date) { %>
    <% if (is_unfulfilled_entitlement) { %> - <% if (user_entitlement.expired_at) { %> - <%- StringUtils.interpolate(gettext('You can no longer select a session. Your final day to select a session was {expiration_date}.'), {expiration_date: user_entitlement.expiration_date}) %> - <% } else { %> + <% if (!user_entitlement.expired_at) { %> <%- StringUtils.interpolate(gettext('You must select a session by {expiration_date} to access the course.'), {expiration_date: user_entitlement.expiration_date}) %> <% } %> <% } else { %> diff --git a/lms/templates/learner_dashboard/course_enroll.underscore b/lms/templates/learner_dashboard/course_enroll.underscore index c12271a201..0038abfb2f 100644 --- a/lms/templates/learner_dashboard/course_enroll.underscore +++ b/lms/templates/learner_dashboard/course_enroll.underscore @@ -16,7 +16,7 @@ <% if (enrollable_course_runs.length > 1) { %>