Skip to content
Snippets Groups Projects
dashboard.html 16.6 KiB
Newer Older
<%page expression_filter="h"/>
<%inherit file="main.html" />
<%def name="online_help_token()"><% return "learnerdashboard" %></%def>
<%namespace name='static' file='static_content.html'/>
import pytz
from datetime import datetime, timedelta
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from django.template import RequestContext
from entitlements.models import CourseEntitlement
from third_party_auth import pipeline
from util.date_utils import strftime_localized
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string
from openedx.core.djangolib.markup import HTML, Text

from student.models import CourseEnrollment

<%
  cert_name_short = settings.CERT_NAME_SHORT
  cert_name_long = settings.CERT_NAME_LONG
%>

Matthew Mongeau's avatar
Matthew Mongeau committed

<%block name="pagetitle">${_("Dashboard")}</%block>
<%block name="bodyclass">view-dashboard is-authenticated</%block>
Will Daly's avatar
Will Daly committed
<%block name="header_extras">
% for template_name in ["donation"]:
<script type="text/template" id="${template_name}-tpl">
  <%static:include path="dashboard/${template_name}.underscore" />
</script>
% endfor
</%block>

  <script src="${static.url('js/commerce/credit.js')}"></script>
Will Daly's avatar
Will Daly committed
  <%static:js group='dashboard'/>
  <script type="text/javascript">
    $(document).ready(function() {
      edx.dashboard.legacy.init({
        dashboard: "${reverse('dashboard') | n, js_escaped_string}",
        signInUser: "${reverse('signin_user') | n, js_escaped_string}",
        changeEmailSettings: "${reverse('change_email_settings') | n, js_escaped_string}"
  <%static:webpack entry="UnenrollmentFactory">
    UnenrollmentFactory({
      urls: {
        dashboard: "${reverse('dashboard') | n, js_escaped_string}",
        signInUser: "${reverse('signin_user') | n, js_escaped_string}",
        changeEmailSettings: "${reverse('change_email_settings') | n, js_escaped_string}",
        browseCourses: "${marketing_link('COURSES') | n, js_escaped_string}"
      },
      isEdx: false
    });
  </%static:webpack>
  <%static:webpack entry="EntitlementUnenrollmentFactory">
    ## Wait until the document is fully loaded before initializing the EntitlementUnenrollmentView
    ## to ensure events are setup correctly.
    $(document).ready(function() {
      EntitlementUnenrollmentFactory({
        dashboardPath: "${reverse('dashboard') | n, js_escaped_string}",
        signInPath: "${reverse('signin_user') | n, js_escaped_string}",
        browseCourses: "${marketing_link('COURSES') | n, js_escaped_string}",
        isEdx: false
  </%static:webpack>
  % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
    <%static:require_module module_name="course_search/js/dashboard_search_factory" class_name="DashboardSearchFactory">
cahrens's avatar
cahrens committed
        DashboardSearchFactory();
    </%static:require_module>
  % if redirect_message:
    <%static:require_module module_name="js/views/message_banner" class_name="MessageBannerView">
        var banner = new MessageBannerView({urgency: 'low', type: 'warning'});
        $('#content').prepend(banner.$el);
        banner.showMessage(${redirect_message | n, dump_js_escaped_json})
    </%static:require_module>
  % endif
<div class="dashboard-notifications" tabindex="-1">

    %if banner_account_activation_message:
        <div class="dashboard-banner">
            ${banner_account_activation_message | n, decode.utf8}
    %endif

    %if enrollment_message:
        <div class="dashboard-banner">
            ${enrollment_message | n,  decode.utf8}

    %if enterprise_message:
        <div class="dashboard-banner">
            ${ enterprise_message | n, decode.utf8 }
        </div>
    %endif

    %if account_activation_messages:
      <div class="activation-message-container">
        % for account_activation_message in account_activation_messages:
          <div class="account-activation ${account_activation_message.tags}" role="alert" aria-label="Account Activation Message" tabindex="-1">
            <div class="message-copy" >
              ${ account_activation_message | n, decode.utf8 }
            </div>
          </div>
        % endfor
      </div>
    %endif

<main id="main" aria-label="Content" tabindex="-1">
    <div class="dashboard" id="dashboard-main">
      % if display_dashboard_courses:
      <div class="main-container">
        <div class="my-courses" id="my-courses">
          <%include file="learner_dashboard/_dashboard_navigation_courses.html"/>

          % if len(course_entitlements + course_enrollments) > 0:
            <ul class="listing-courses">
            <%
                share_settings = configuration_helpers.get_value(
                    'SOCIAL_SHARING_SETTINGS',
                    getattr(settings, 'SOCIAL_SHARING_SETTINGS', {})
                )
            %>
            % for dashboard_index, enrollment in enumerate(course_entitlements + course_enrollments):
              <%
                # Check if the course run is an entitlement and if it has an associated session
                entitlement = enrollment if isinstance(enrollment, CourseEntitlement) else None
                entitlement_session = entitlement.enrollment_course_run if entitlement else None
                entitlement_days_until_expiration = entitlement.get_days_until_expiration() if entitlement else None
                entitlement_expiration = datetime.now(tz=pytz.UTC) + timedelta(days=entitlement_days_until_expiration) if (entitlement and entitlement_days_until_expiration < settings.ENTITLEMENT_EXPIRED_ALERT_PERIOD) else None
                entitlement_expiration_date = strftime_localized(entitlement_expiration, 'SHORT_DATE') if entitlement and entitlement_expiration else None
                entitlement_expired_at = strftime_localized(entitlement.expired_at_datetime, 'SHORT_DATE') if entitlement and entitlement.expired_at_datetime else None

                is_fulfilled_entitlement = True if entitlement and entitlement_session else False
                is_unfulfilled_entitlement = True if entitlement and not entitlement_session else False

                entitlement_available_sessions = []
                if entitlement:
                  # Grab the available, enrollable sessions for a given entitlement and scrape them for relevant attributes
                  entitlement_available_sessions = [{
                    'session_id': course['key'],
                    'enrollment_end': course['enrollment_end'],
                    'pacing_type': course['pacing_type'],
                    'advertised_start': CourseOverview.get_from_id(CourseKey.from_string(course['key'])).advertised_start,
                    'start': CourseOverview.get_from_id(CourseKey.from_string(course['key'])).start,
                    'end': CourseOverview.get_from_id(CourseKey.from_string(course['key'])).end,
                    } for course in course_entitlement_available_sessions[str(entitlement.uuid)]]
                  if is_fulfilled_entitlement:
                    # If the user has a fulfilled entitlement, pass through the entitlements CourseEnrollment object
                    enrollment = entitlement_session
                  else:
                    # If the user has an unfulfilled entitlement, pass through a bare CourseEnrollment object to populate card with metadata
                    pseudo_session = unfulfilled_entitlement_pseudo_sessions[str(entitlement.uuid)]
                    if not pseudo_session:
                    enrollment = CourseEnrollment(user=user, course_id=pseudo_session['key'], mode=pseudo_session['type'])
                  # We only show email settings for entitlement cards if the entitlement has an associated enrollment
                  show_email_settings = is_fulfilled_entitlement and (entitlement_session.course_id in show_email_settings_for)
                else:
                  show_email_settings = (enrollment.course_id in show_email_settings_for)
                session_id = enrollment.course_id
                show_courseware_link = (session_id in show_courseware_links_for)
                cert_status = cert_statuses.get(session_id)
                can_refund_entitlement = entitlement and entitlement.is_entitlement_refundable()
                can_unenroll = (not cert_status) or cert_status.get('can_unenroll') if not unfulfilled_entitlement else False
                credit_status = credit_statuses.get(session_id)
                course_mode_info = all_course_modes.get(session_id)
                is_paid_course = True if entitlement else (session_id in enrolled_courses_either_paid)
                is_course_blocked = (session_id in block_courses)
                course_verification_status = verification_status_by_course.get(session_id, {})
                course_requirements = courses_requirements_not_met.get(session_id)
                related_programs = inverted_programs.get(unicode(entitlement.course_uuid if is_unfulfilled_entitlement else session_id))
                show_consent_link = (session_id in consent_required_courses)
                course_overview = enrollment.course_overview
                resume_button_url = resume_button_urls[dashboard_index]
              <%include file='dashboard/_dashboard_course_listing.html' args='course_overview=course_overview, course_card_index=dashboard_index, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, is_fulfilled_entitlement=is_fulfilled_entitlement, entitlement=entitlement, entitlement_session=entitlement_session, entitlement_available_sessions=entitlement_available_sessions, entitlement_expiration_date=entitlement_expiration_date, entitlement_expired_at=entitlement_expired_at, show_courseware_link=show_courseware_link, cert_status=cert_status, can_refund_entitlement=can_refund_entitlement, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, is_course_blocked=is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard, show_consent_link=show_consent_link, enterprise_customer_name=enterprise_customer_name, resume_button_url=resume_button_url' />
            </ul>
          % else:
            <div class="empty-dashboard-message">
              <p>${_("You are not enrolled in any courses yet.")}</p>
              % if empty_dashboard_message:
                <p class="custom-message">${empty_dashboard_message | n, decode.utf8}</p>
              %endif
              % if settings.FEATURES.get('COURSES_ARE_BROWSABLE'):
                <a class="btn btn-primary" href="${marketing_link('COURSES')}">
                  ${_("Explore courses")}
                </a>

              %endif
          </div>
          % endif

          % if staff_access and len(errored_courses) > 0:
            <div id="course-errors">
              <h2>${_("Course-loading errors")}</h2>

            % for course_dir, errors in errored_courses.items():
               <h3>${course_dir}</h3>
                   <ul>
                 % for (msg, err) in errors:
                     <li>${msg}
                       <ul><li><pre>${err}</pre></li></ul>
                     </li>
                 % endfor
                   </ul>
            % endfor
      <div class="side-container">
          <div class="sidebar-notification">
            ${sidebar_account_activation_message | n, decode.utf8}
          </div>
        %endif

        % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
          <div id="dashboard-search-bar" class="search-bar dashboard-search-bar" role="search" aria-label="Dashboard">
            <form class="search-form">
              <label for="dashboard-search-input">${_('Search Your Courses')}</label>
              <div class="search-field-wrapper">
                <input id="dashboard-search-input" type="text" class="search-field"/>
                <button type="submit" class="search-button" title="${_('Search')}">
                  <span class="icon fa fa-search" aria-hidden="true"></span>
                </button>
                <button type="button" class="cancel-button" title="${_('Clear search')}">
                  <span class="icon fa fa-remove" aria-hidden="true"></span>
                </button>
              </div>
            </form>
          </div>
          <div id="dashboard-search-results" class="search-results dashboard-search-results"></div>
        % endif
        % if display_sidebar_on_dashboard:
          <div class="profile-sidebar" id="profile-sidebar" role="region" aria-label="Account Status Info">
            <header class="profile">
              <h2 class="account-status-title sr">${_("Account Status Info")}: </h2>
            </header>
            <div class="user-info">
              <ul>

                % if len(order_history_list):
                <li class="order-history">
                  <span class="title">${_("Order History")}</span>
                  % for order_history_item in order_history_list:
                    <span><a href="${order_history_item['receipt_url']}" target="_blank" class="edit-name">${order_history_item['order_date']}</a></span>
                  % endfor
                </li>
                % endif

                <%include file="${static.get_template_path('dashboard/_dashboard_status_verification.html')}" />

              </ul>
            </div>
<div id="email-settings-modal" class="modal" aria-hidden="true">
  <div class="inner-wrapper" role="dialog" aria-labelledby="email-settings-title">
    <button class="close-modal">
      <span class="icon fa fa-remove" aria-hidden="true"></span>
      <span class="sr">
        ## Translators: this is a control to allow users to exit out of this modal interface (a menu or piece of UI that takes the full focus of the screen)
      <h2 id="email-settings-title">
        ${Text(_("Email Settings for {course_number}")).format(course_number=HTML('<span id="email_settings_course_number"></span>'))}
        <span class="sr">,
          ## Translators: this text gives status on if the modal interface (a menu or piece of UI that takes the full focus of the screen) is open or not
      <hr/>
    </header>

    <form id="email_settings_form" method="post">
      <input name="course_id" id="email_settings_course_id" type="hidden" />
      <label><input type="checkbox" id="receive_emails" name="receive_emails" />${_("Receive course emails")} </label>
        <input type="submit" id="submit" value="${_("Save Settings")}" />
<div id="unenroll-modal" class="modal unenroll-modal" aria-hidden="true">
  <div class="inner-wrapper" role="dialog" aria-labelledby="unenrollment-modal-title" aria-live="polite">
    <button class="close-modal">
      <span class="icon fa fa-remove" aria-hidden="true"></span>
      <span class="sr">
        ## Translators: this is a control to allow users to exit out of this modal interface (a menu or piece of UI that takes the full focus of the screen)
    <header class="unenroll-header">
      <h2 id="unenrollment-modal-title">
        <span id='track-info'></span>
        <span id='refund-info'></span>
        <span class="sr">,
          ## Translators: this text gives status on if the modal interface (a menu or piece of UI that takes the full focus of the screen) is open or not
      <hr/>
    </header>
    <div id="unenroll_error" class="modal-form-error"></div>
    <form id="unenroll_form" method="post" data-remote="true" action="${reverse('change_enrollment')}">
      <input name="course_id" id="unenroll_course_id" type="hidden" />
      <input name="enrollment_action" type="hidden" value="unenroll" />
      <div class="submit">
        <input class="submit-button" name="submit" type="submit" value="${_("Unenroll")}" />

<%include file="dashboard/_dashboard_entitlement_unenrollment_modal.html"/>