Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Display Basic Course Information
Browse files Browse the repository at this point in the history
  • Loading branch information
bradenmacdonald committed Nov 3, 2015
1 parent cc12a84 commit 0e842b8
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 1 deletion.
32 changes: 32 additions & 0 deletions analytics_dashboard/courses/templates/courses/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,36 @@
</div>
{% endfor %}
</div>

{% if course_overview or external_course_tools %}
<div class="row">
<div class="col-sm-12"><hr></div>
</div>

<div class="row">
<div class="col-sm-8">
{% if course_overview %}
<h4 class="section-title">{% trans "Basic Course Information" %}</h4>
<table class="table course-overview" role="presentation">
<tbody>
{% for label, value in course_overview %}
<tr><th>{{label}}</th><td>{{value|safe}}</td></tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
{% if external_course_tools %}
<div class="col-sm-4">
{# Translators: This title describes a list of links to outside tools for this course. #}
<h4 class="section-title">{% trans "External Tools" %}</h4>
<ul class="course-external-tools">
{% for tool in external_course_tools %}
<li><a href="{{tool.url}}"><i class="ico fa {{tool.icon}}" aria-hidden="true"></i>{{tool.title}}</a></li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% endif %}
{% endblock %}
4 changes: 3 additions & 1 deletion analytics_dashboard/courses/tests/test_views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,11 @@ def mock_course_api(self, path, body=None, **kwargs):
httpretty.register_uri(httpretty.GET, url, **default_kwargs)
logger.debug('Mocking Course API URL: %s', url)

def mock_course_detail(self, course_id):
def mock_course_detail(self, course_id, extra=None):
path = 'courses/{}'.format(course_id)
body = {'id': course_id, 'name': mock_course_name(course_id)}
if extra:
body.update(extra)
self.mock_course_api(path, body)

def mock_course_list(self):
Expand Down
30 changes: 30 additions & 0 deletions analytics_dashboard/courses/tests/test_views/test_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,36 @@ def assertViewIsValid(self, course_id):
def test_missing_data(self, course_id):
self.skipTest('The course homepage does not check for the existence of a course.')

@httpretty.activate
def test_course_overview(self):
self.toggle_switch('enable_course_api', True)
self.mock_course_detail(DEMO_COURSE_ID, {'start': '2015-01-23T00:00:00Z', 'end': None})
response = self.client.get(self.path(course_id=DEMO_COURSE_ID))
self.assertEqual(response.status_code, 200)

overview_data = {k: v for k, v in response.context['course_overview']}
self.assertEqual(overview_data.get('Start Date'), 'January 23, 2015')
self.assertEqual(overview_data.get('Status'), 'In Progress')
links = {link['title']: link['url'] for link in response.context['external_course_tools']}
self.assertEqual(len(links), 3)
self.assertEqual(links.get('Instructor Dashboard'), 'http://lms-host/{}/instructor'.format(DEMO_COURSE_ID))
self.assertEqual(links.get('Courseware'), 'http://lms-host/{}/courseware'.format(DEMO_COURSE_ID))
self.assertEqual(links.get('Studio'), 'http://cms-host/{}'.format(DEMO_COURSE_ID))

@httpretty.activate
def test_course_ended(self):
self.toggle_switch('enable_course_api', True)
self.mock_course_detail(DEMO_COURSE_ID, {
'start': '2015-01-01T00:00:00Z',
'end': '2015-02-15T00:00:00Z'
})
response = self.client.get(self.path(course_id=DEMO_COURSE_ID))
self.assertEqual(response.status_code, 200)
overview_data = {k: v for k, v in response.context['course_overview']}
self.assertEqual(overview_data.get('Start Date'), 'January 01, 2015')
self.assertEqual(overview_data.get('End Date'), 'February 15, 2015')
self.assertEqual(overview_data.get('Status'), 'Ended')


class CourseIndexViewTests(CourseAPIMixin, ViewTestMixin, CoursePermissionsExceptionMixin, TestCase):
viewname = 'courses:index'
Expand Down
59 changes: 59 additions & 0 deletions analytics_dashboard/courses/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from braces.views import LoginRequiredMixin
from ccx_keys.locator import CCXLocator
from datetime import datetime
from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
Expand Down Expand Up @@ -525,6 +526,64 @@ def get_context_data(self, **kwargs):
})

context['page_data'] = self.get_page_data(context)

overview_data = []
if self.course_api_enabled:
if switch_is_active('display_course_name_in_nav'):
# Translators: 'Course ID' is 'Course Identifier', the unique code that identifies the course
overview_data.append((_('Course ID'), self.course_id))
else:
overview_data.append((_('Course Name'), self.course_info.get('name')))

def parse_course_date(date_str):
return datetime.strptime(date_str, CourseStructureApiClient.DATETIME_FORMAT) if date_str else None

def format_date(date):
return dateformat.format(date, settings.DATE_FORMAT) if date else "--"

start_date = parse_course_date(self.course_info.get('start'))
end_date = parse_course_date(self.course_info.get('end'))
todays_date = datetime.now()
status_str = '--'
if start_date:
if todays_date >= start_date:
in_progress = (end_date is None or end_date > todays_date)
# Translators: 'In Progress' and 'Ended' refer to whether students are
# actively using the course or it is over.
status_str = _('In Progress') if in_progress else _('Ended')
else:
# Translators: This refers to a course that has not yet begun.
status_str = _('Not Started Yet')
overview_data += [
(_('Start Date'), format_date(start_date)),
(_('End Date'), format_date(end_date)),
(_('Status'), status_str),
]

context['course_overview'] = overview_data

external_tools = []

if settings.LMS_COURSE_SHORTCUT_BASE_URL:
external_tools.append({
'title': _('Instructor Dashboard'),
'url': "{}/{}/instructor".format(settings.LMS_COURSE_SHORTCUT_BASE_URL, self.course_id),
'icon': 'fa-dashboard',
})
external_tools.append({
'title': _('Courseware'),
'url': "{}/{}/courseware".format(settings.LMS_COURSE_SHORTCUT_BASE_URL, self.course_id),
'icon': 'fa-pencil-square-o',
})
if settings.CMS_COURSE_SHORTCUT_BASE_URL:
external_tools.append({
# Translators: This is the name of the edX Course Editor (the CMS)
'title': _('Studio'),
'url': "{}/{}".format(settings.CMS_COURSE_SHORTCUT_BASE_URL, self.course_id),
'icon': 'fa-sliders',
})
context['external_course_tools'] = external_tools

return context


Expand Down
3 changes: 3 additions & 0 deletions analytics_dashboard/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@
# used to construct the shortcut link to course modules
LMS_COURSE_SHORTCUT_BASE_URL = None

# used to construct shortcusts to view/edit courses in Studio
CMS_COURSE_SHORTCUT_BASE_URL = None

# Used to determine how dates are displayed in templates
DATE_FORMAT = 'F d, Y'

Expand Down
1 change: 1 addition & 0 deletions analytics_dashboard/settings/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'

LMS_COURSE_SHORTCUT_BASE_URL = 'https://example.com/courses'
CMS_COURSE_SHORTCUT_BASE_URL = 'https://studio.example.com/course'

########## BRANDING
PLATFORM_NAME = 'Open edX'
Expand Down
1 change: 1 addition & 0 deletions analytics_dashboard/settings/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
SOCIAL_AUTH_EDX_OIDC_URL_ROOT = 'http://example.com'

LMS_COURSE_SHORTCUT_BASE_URL = 'http://lms-host'
CMS_COURSE_SHORTCUT_BASE_URL = 'http://cms-host'
COURSE_API_URL = 'http://course-api-host'

LOGGING = get_logger_config(debug=DEBUG, dev_env=True, local_loglevel='DEBUG')
Expand Down
26 changes: 26 additions & 0 deletions analytics_dashboard/static/sass/_developer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,32 @@ table.dataTable thead th.sorting_desc:after {
}
}

.table.course-overview {
th, td {
border-top: none;
}

th {
font-weight: normal;
white-space: nowrap;
}

td {
width: 99%; // Expand as much as possible
}
}

.course-external-tools {
list-style: none;
padding: 0;

li {
padding: 8px 10px;
}

.ico { margin-right: 6px; }
}

.course-home-table-outer {
header.heading-outer {
display: table;
Expand Down

0 comments on commit 0e842b8

Please sign in to comment.