Upcoming Dates', - '
time til end (end date shown) - {'weeks_to_complete': 4}, # Weeks to complete < time til end (end date not shown) - ) - def test_course_end_date_self_paced(self, cr_details): - """ - In self-paced courses, the end date will now only show up if the learner - views the course within the course's weeks to complete (as defined in - the course-discovery service). E.g. if the weeks to complete is 5 weeks - and the course doesn't end for 10 weeks, there will be no end date, but - if the course ends in 3 weeks, the end date will appear. - """ - now = datetime.now(utc) - end_timedelta_number = 5 - course = CourseFactory.create( - start=now + timedelta(days=-7), end=now + timedelta(weeks=end_timedelta_number), self_paced=True) - user = create_user() - with patch('lms.djangoapps.courseware.date_summary.get_course_run_details') as mock_get_cr_details: - mock_get_cr_details.return_value = cr_details - block = CourseEndDate(course, user) - self.assertEqual(block.title, 'Course End') - if cr_details['weeks_to_complete'] > end_timedelta_number: - self.assertEqual(block.date, course.end) - else: - self.assertIsNone(block.date) - def test_ecommerce_checkout_redirect(self): """Verify the block link redirects to ecommerce checkout if it's enabled.""" sku = 'TESTSKU' diff --git a/lms/djangoapps/courseware/utils.py b/lms/djangoapps/courseware/utils.py deleted file mode 100644 index a378ace954..0000000000 --- a/lms/djangoapps/courseware/utils.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Utility functions that have to do with the courseware.""" - - -import datetime - -from lms.djangoapps.commerce.utils import EcommerceService -from pytz import utc - -from course_modes.models import CourseMode - - -def verified_upgrade_deadline_link(user, course=None, course_id=None): - """ - Format the correct verified upgrade link for the specified ``user`` - in a course. - - One of ``course`` or ``course_id`` must be supplied. If both are specified, - ``course`` will take priority. - - Arguments: - user (:class:`~django.contrib.auth.models.User`): The user to display - the link for. - course (:class:`.CourseOverview`): The course to render a link for. - course_id (:class:`.CourseKey`): The course_id of the course to render for. - - Returns: - The formatted link that will allow the user to upgrade to verified - in this course. - """ - if course is not None: - course_id = course.id - return EcommerceService().upgrade_url(user, course_id) - - -def verified_upgrade_link_is_valid(enrollment=None): - """ - Return whether this enrollment can be upgraded. - - Arguments: - enrollment (:class:`.CourseEnrollment`): The enrollment under consideration. - If None, then the enrollment is considered to be upgradeable. - """ - # Return `true` if user is not enrolled in course - if enrollment is None: - return False - - upgrade_deadline = enrollment.upgrade_deadline - - if upgrade_deadline is None: - return False - - if datetime.datetime.now(utc).date() > upgrade_deadline.date(): - return False - - # Show the summary if user enrollment is in which allow user to upsell - return enrollment.is_active and enrollment.mode in CourseMode.UPSELL_TO_VERIFIED_MODES diff --git a/lms/djangoapps/experiments/utils.py b/lms/djangoapps/experiments/utils.py index 3e4420e33f..c0a524f75f 100644 --- a/lms/djangoapps/experiments/utils.py +++ b/lms/djangoapps/experiments/utils.py @@ -13,7 +13,7 @@ from opaque_keys.edx.keys import CourseKey from course_modes.models import format_course_price, get_cosmetic_verified_display_price, CourseMode from lms.djangoapps.courseware.access import has_staff_access_to_preview_mode -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link, verified_upgrade_link_is_valid from entitlements.models import CourseEntitlement from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.catalog.utils import get_programs diff --git a/lms/djangoapps/experiments/views_custom.py b/lms/djangoapps/experiments/views_custom.py index 9e10d9d9cd..99d20d8fac 100644 --- a/lms/djangoapps/experiments/views_custom.py +++ b/lms/djangoapps/experiments/views_custom.py @@ -23,7 +23,7 @@ from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiv from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin -from lms.djangoapps.courseware.utils import verified_upgrade_link_is_valid +from lms.djangoapps.courseware.date_summary import verified_upgrade_link_is_valid from course_modes.models import get_cosmetic_verified_display_price from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.experiments.stable_bucketing import stable_bucketing_hash_group diff --git a/lms/static/sass/features/_course-experience.scss b/lms/static/sass/features/_course-experience.scss index b1fe70780b..3f91244b4f 100644 --- a/lms/static/sass/features/_course-experience.scss +++ b/lms/static/sass/features/_course-experience.scss @@ -14,8 +14,8 @@ text-align: center; } - &:not(:last-child) { - margin-bottom: 32px; + &:not(:first-child) { + margin-top: $baseline; } } } @@ -412,69 +412,64 @@ } // date summary -.date-summary { - @include clearfix; +.date-summary-container { + .date-summary { + @include clearfix; - display: flex; - justify-content: space-between; - padding: 12px 0; - &:last-of-type { - padding-bottom: 0; - } + display: flex; + justify-content: space-between; + padding: $baseline/2 $baseline/2 $baseline/2 0; - .left-column { - flex: 0 0 24px; + .left-column { + flex: 5%; - .calendar-icon { - margin-top: 4px; - height: 1em; - width: 16px; - background: url('#{$static-path}/images/calendar-alt-regular.svg'); - background-repeat: no-repeat; - } - } - - .right-column { - flex: auto; - - .localized-datetime { - font-weight: $font-weight-bold; - margin-bottom: 8px; + .calendar-icon { + margin-top: 3px; + height: 1em; + width: auto; + background: url('#{$static-path}/images/calendar-alt-regular.svg'); + background-repeat: no-repeat; + } } - .heading { - font: -apple-system-body; - line-height: 1.5; - font-weight: $font-bold; - color: theme-color("dark"); + .right-column { + flex: 85%; - a { + .localized-datetime { + font-weight: $font-weight-bold; + margin-bottom: 8px; + } + + .heading { + font: -apple-system-body; + line-height: 1; + font-weight: $font-bold; + color: theme-color("dark"); + } + + .description { + margin-bottom: $baseline/2; + display: inline-block; + } + + .heading, .description { + font-size: 0.9rem; + } + + .date-summary-link { font-weight: $font-semibold; + + a { + color: $link-color; + font-weight: $font-regular; + } } } - .description { - margin-bottom: 0; - display: inline-block; + .date { + color: theme-color("dark"); + font: -apple-system-body; } - - .heading, .description { - font-size: 0.9rem; - } - - .date-summary-link { - font-weight: $font-semibold; - - a { - color: $link-color; - font-size: 0.9rem; - } - } - } - - .date { - color: theme-color("dark"); - font: -apple-system-body; } } diff --git a/openedx/core/djangoapps/schedules/resolvers.py b/openedx/core/djangoapps/schedules/resolvers.py index 6437e28238..c7b22a07d0 100644 --- a/openedx/core/djangoapps/schedules/resolvers.py +++ b/openedx/core/djangoapps/schedules/resolvers.py @@ -14,7 +14,7 @@ from edx_ace.recipient import Recipient from edx_ace.recipient_resolver import RecipientResolver from edx_django_utils.monitoring import function_trace, set_custom_metric -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link, verified_upgrade_link_is_valid from lms.djangoapps.discussion.notification_prefs.views import UsernameCipher from openedx.core.djangoapps.ace_common.template_context import get_base_template_context from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH diff --git a/openedx/features/course_duration_limits/access.py b/openedx/features/course_duration_limits/access.py index 6dfd476157..1b5ed1323b 100644 --- a/openedx/features/course_duration_limits/access.py +++ b/openedx/features/course_duration_limits/access.py @@ -17,7 +17,7 @@ from web_fragments.fragment import Fragment from course_modes.models import CourseMode from lms.djangoapps.courseware.access_response import AccessError from lms.djangoapps.courseware.access_utils import ACCESS_GRANTED -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link +from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link from lms.djangoapps.courseware.masquerade import get_course_masquerade, is_masquerading_as_specific_student from openedx.core.djangoapps.catalog.utils import get_course_run_details from openedx.core.djangoapps.content.course_overviews.models import CourseOverview diff --git a/openedx/features/course_experience/templates/course_experience/dates-summary.html b/openedx/features/course_experience/templates/course_experience/dates-summary.html index e8a66c083b..36952923c8 100644 --- a/openedx/features/course_experience/templates/course_experience/dates-summary.html +++ b/openedx/features/course_experience/templates/course_experience/dates-summary.html @@ -2,24 +2,26 @@ from django.utils.translation import ugettext as _ %> <%page args="course_date" expression_filter="h"/> -
${course_date.description}
- % endif - % if course_date.link and course_date.link_text: - - % endif +${course_date.description}
+ % endif + % if course_date.link and course_date.link_text: + + ${course_date.link_text} + + % endif +