Commit f3a670f7 by Awais

ECOM-4888

Basic app structure.
parent be062b4f
import ddt
from django.core.urlresolvers import reverse
from django.forms import model_to_dict
......@@ -5,6 +6,7 @@ from django.test import TestCase
from course_discovery.apps.publisher.models import Course, CourseRun, Seat
from course_discovery.apps.publisher.tests import factories
from course_discovery.apps.publisher.wrappers import CourseRunWrapper
class CreateUpdateCourseViewTests(TestCase):
......@@ -178,3 +180,142 @@ class SeatsCreateUpdateViewTests(TestCase):
status_code=302,
target_status_code=200
)
@ddt.ddt
class CourseRunDetailTests(TestCase):
""" Tests for the course-run detail view. """
def setUp(self):
super(CourseRunDetailTests, self).setUp()
self.course = factories.CourseFactory()
self.course_run = factories.CourseRunFactory(course=self.course)
self._generate_seats([Seat.AUDIT, Seat.HONOR, Seat.VERIFIED, Seat.PROFESSIONAL])
self._generate_credit_seat()
self.page_url = reverse('publisher:publisher_course_run_detail', args=[self.course_run.id])
self.wrapped_course_run = CourseRunWrapper(self.course_run)
self.date_format = '%b %d, %Y, %H:%M:%S %p'
def test_page_without_data(self):
""" Verify that detail page without any data available for that course-run. """
course_run = factories.CourseRunFactory(course=self.course)
page_url = reverse('publisher:publisher_course_run_detail', args=[course_run.id])
response = self.client.get(page_url)
self.assertEqual(response.status_code, 200)
def _generate_seats(self, modes):
""" Helper method to add seats for a course-run. """
for mode in modes:
factories.SeatFactory(type=mode, course_run=self.course_run)
def _generate_credit_seat(self):
""" Helper method to add credit seat for a course-run. """
factories.SeatFactory(type='credit', course_run=self.course_run, credit_provider='ASU', credit_hours=9)
def test_course_run_detail_page(self):
""" Verify that detail page contains all the data for drupal, studio and
cat.
"""
response = self.client.get(self.page_url)
self.assertEqual(response.status_code, 200)
self._assert_credits_seats(response, self.wrapped_course_run.credit_seat)
self._assert_non_credits_seats(response, self.wrapped_course_run.non_credit_seats)
self._assert_studio_fields(response)
self._assert_cat(response)
self._assert_drupal(response)
self._assert_subjects(response)
def _assert_credits_seats(self, response, seat):
""" Helper method to test to all credit seats. """
self.assertContains(response, 'Credit Seats')
self.assertContains(response, 'Credit Provider')
self.assertContains(response, 'Price')
self.assertContains(response, 'Currency')
self.assertContains(response, 'Credit Hours')
self.assertContains(response, seat.credit_provider)
self.assertContains(response, seat.price)
self.assertContains(response, seat.currency.name)
self.assertContains(response, seat.credit_hours)
def _assert_non_credits_seats(self, response, seats):
""" Helper method to test to all non-credit seats. """
self.assertContains(response, 'Seat Type')
self.assertContains(response, 'Price')
self.assertContains(response, 'Currency')
self.assertContains(response, 'Upgrade Deadline')
for seat in seats:
self.assertContains(response, seat.type)
self.assertContains(response, seat.price)
self.assertContains(response, seat.currency)
def _assert_studio_fields(self, response):
""" Helper method to test studio values and labels. """
fields = [
'Course Name', 'Organization', 'Number', 'Start Date', 'End Date',
'Enrollment Start Date', 'Enrollment End Date', 'Pacing Type'
]
for field in fields:
self.assertContains(response, field)
values = [
self.wrapped_course_run.title, self.wrapped_course_run.number,
self.course_run.pacing_type
]
for value in values:
self.assertContains(response, value)
self._assert_dates(response)
def _assert_drupal(self, response):
""" Helper method to test drupal values and labels. """
fields = [
'Title', 'Number', 'Course ID', 'Price', 'Sub Title', 'School', 'Subject', 'XSeries',
'Start Date', 'End Date', 'Self Paced', 'Staff', 'Estimated Effort', 'Languages',
'Video Translations', 'Level', 'About this Course', "What you'll learn",
'Prerequisite', 'Keywords', 'Sponsors', 'Enrollments'
]
for field in fields:
self.assertContains(response, field)
values = [
self.wrapped_course_run.title, self.wrapped_course_run.lms_course_id,
self.wrapped_course_run.verified_seat_price, self.wrapped_course_run.short_description,
self.wrapped_course_run.xseries_name, self.wrapped_course_run.min_effort,
self.wrapped_course_run.pacing_type, self.wrapped_course_run.persons,
self.wrapped_course_run.max_effort, self.wrapped_course_run.language.name,
self.wrapped_course_run.video_languages, self.wrapped_course_run.level_type,
self.wrapped_course_run.full_description, self.wrapped_course_run.expected_learnings,
self.wrapped_course_run.prerequisites, self.wrapped_course_run.keywords
]
for value in values:
self.assertContains(response, value)
for seat in self.wrapped_course_run.wrapped_obj.seats.all():
self.assertContains(response, seat.type)
def _assert_cat(self, response):
""" Helper method to test cat data. """
fields = [
'Course ID', 'Course Type'
]
values = [self.course_run.lms_course_id]
for field in fields:
self.assertContains(response, field)
for value in values:
self.assertContains(response, value)
def _assert_dates(self, response):
""" Helper method to test all dates. """
for value in [
self.course_run.start, self.course_run.end,
self.course_run.enrollment_start, self.course_run.enrollment_end
]:
self.assertContains(response, value.strftime(self.date_format))
def _assert_subjects(self, response):
""" Helper method to test course subjects. """
for subject in self.wrapped_course_run.subjects:
self.assertContains(response, subject.name)
# pylint: disable=no-member
import ddt
from django.test import TestCase
from unittest import mock
from course_discovery.apps.course_metadata.tests.factories import CourseRunFactory, OrganizationFactory
from course_discovery.apps.course_metadata.models import CourseOrganization
from course_discovery.apps.course_metadata.tests.factories import OrganizationFactory
from course_discovery.apps.publisher.tests import factories
from course_discovery.apps.publisher.wrappers import CourseRunWrapper
from course_discovery.apps.publisher.models import Seat
@ddt.ddt
class CourseRunWrapperTests(TestCase):
""" Tests for the publisher `BaseWrapper` model. """
def setUp(self):
super(CourseRunWrapperTests, self).setUp()
self.course_run = CourseRunFactory()
course = self.course_run.course
self.course_run = factories.CourseRunFactory()
self.course = self.course_run.course
organization_1 = OrganizationFactory()
organization_2 = OrganizationFactory()
CourseOrganization.objects.create(
course=course,
organization=organization_1,
relation_type=CourseOrganization.OWNER
)
CourseOrganization.objects.create(
course=course,
organization=organization_2,
relation_type=CourseOrganization.OWNER
)
course.save()
self.course.organizations.add(organization_1)
self.course.organizations.add(organization_2)
self.course.save()
self.wrapped_course_run = CourseRunWrapper(self.course_run)
......@@ -41,7 +37,7 @@ class CourseRunWrapperTests(TestCase):
def test_model_attr(self):
""" Verify that the wrapper passes through object values not defined on wrapper. """
self.assertEqual(self.wrapped_course_run.key, self.course_run.key)
self.assertEqual(self.wrapped_course_run.lms_course_id, self.course_run.lms_course_id)
def test_callable(self):
mock_callable = mock.Mock(return_value='callable_value')
......@@ -49,3 +45,53 @@ class CourseRunWrapperTests(TestCase):
wrapper = CourseRunWrapper(mock_obj)
self.assertEqual(wrapper.callable_attr(), 'callable_value')
def _generate_seats(self, modes):
for mode in modes:
factories.SeatFactory(type=mode, course_run=self.course_run)
@ddt.unpack
@ddt.data(
([], Seat.AUDIT),
([Seat.AUDIT], Seat.AUDIT),
([Seat.AUDIT, Seat.CREDIT, Seat.VERIFIED], Seat.CREDIT),
([Seat.AUDIT, Seat.VERIFIED], Seat.VERIFIED),
([Seat.PROFESSIONAL], Seat.PROFESSIONAL),
)
def test_course_type_(self, seats_list, course_type):
""" Verify that the wrapper return the course type according to the
available seats.
"""
self._generate_seats(seats_list)
wrapper_object = CourseRunWrapper(self.course_run)
self.assertEqual(wrapper_object.course_type, course_type)
def test_organization_key(self):
""" Verify that the wrapper return the organization key. """
course = factories.CourseFactory()
course_run = factories.CourseRunFactory(course=course)
wrapped_course_run = CourseRunWrapper(course_run)
self.assertEqual(wrapped_course_run.organization_key, None)
organization = OrganizationFactory()
course.organizations.add(organization)
wrapped_course_run = CourseRunWrapper(course_run)
self.assertEqual(wrapped_course_run.organization_key, organization.key)
def test_verified_seat_price(self):
""" Verify that the wrapper return the verified seat price. """
self.assertEqual(self.wrapped_course_run.verified_seat_price, None)
seat = factories.SeatFactory(type=Seat.VERIFIED, course_run=self.course_run)
wrapped_course_run = CourseRunWrapper(self.course_run)
self.assertEqual(wrapped_course_run.verified_seat_price, seat.price)
def test_credit_seat(self):
""" Verify that the wrapper return the credit seat. """
self.assertEqual(self.wrapped_course_run.credit_seat, None)
seat = factories.SeatFactory(
type=Seat.CREDIT, course_run=self.course_run, credit_provider='ASU', credit_hours=9
)
wrapped_course_run = CourseRunWrapper(self.course_run)
self.assertEqual(wrapped_course_run.credit_seat, seat)
......@@ -8,10 +8,10 @@ from course_discovery.apps.publisher import views
urlpatterns = [
url(r'^courses/new$', views.CreateCourseView.as_view(), name='publisher_courses_new'),
url(r'^courses/(?P<pk>\d+)/edit/$', views.UpdateCourseView.as_view(), name='publisher_courses_edit'),
url(r'^course_runs/(?P<pk>\d+)/$', views.CourseRunDetailView.as_view(), name='publisher_course_run_detail'),
url(r'^course_runs/$', views.CourseRunListView.as_view(), name='publisher_course_runs'),
url(r'^course_runs/new$', views.CreateCourseRunView.as_view(), name='publisher_course_runs_new'),
url(r'^course_runs/(?P<pk>\d+)/edit/$', views.UpdateCourseRunView.as_view(), name='publisher_course_runs_edit'),
url(r'^seats/new$', views.CreateSeatView.as_view(), name='publisher_seats_new'),
url(r'^seats/(?P<pk>\d+)/edit/$', views.UpdateSeatView.as_view(), name='publisher_seats_edit'),
]
......@@ -3,6 +3,7 @@ Course publisher views.
"""
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.list import ListView
from course_discovery.apps.publisher.forms import CourseForm, CourseRunForm, SeatForm
......@@ -122,3 +123,14 @@ class UpdateSeatView(UpdateView):
def get_success_url(self):
return reverse(self.success_url, kwargs={'pk': self.object.id})
class CourseRunDetailView(DetailView):
""" Course RunDetail View."""
model = CourseRun
template_name = 'publisher/run_detail/home.html'
def get_context_data(self, **kwargs):
context = super(CourseRunDetailView, self).get_context_data(**kwargs)
context['object'] = CourseRunWrapper(context['object'])
return context
"""Publisher Wrapper Classes"""
from course_discovery.apps.publisher.models import Seat
class BaseWrapper(object):
......@@ -24,3 +25,81 @@ class CourseRunWrapper(BaseWrapper):
@property
def partner(self):
return '/'.join([org.key for org in self.wrapped_obj.course.organizations.all()])
@property
def credit_seat(self):
credit_seat = [seat for seat in self.wrapped_obj.seats.all() if seat.type == Seat.CREDIT]
if not credit_seat:
return None
return credit_seat[0]
@property
def non_credit_seats(self):
return [seat for seat in self.wrapped_obj.seats.all() if seat.type != Seat.CREDIT]
@property
def video_languages(self):
return ', '.join([lang.name for lang in self.wrapped_obj.transcript_languages.all()])
@property
def persons(self):
return ', '.join([person.name for person in self.wrapped_obj.staff.all()])
@property
def verified_seat_price(self):
seats = [seat for seat in self.wrapped_obj.seats.all() if seat.type == Seat.VERIFIED]
if not seats:
return None
return seats[0].price
@property
def number(self):
return self.wrapped_obj.course.number
@property
def short_description(self):
return self.wrapped_obj.course.short_description
@property
def level_type(self):
return self.wrapped_obj.course.level_type
@property
def full_description(self):
return self.wrapped_obj.course.full_description
@property
def expected_learnings(self):
return self.wrapped_obj.course.expected_learnings
@property
def prerequisites(self):
return self.wrapped_obj.course.prerequisites
@property
def subjects(self):
return [
self.wrapped_obj.course.primary_subject,
self.wrapped_obj.course.secondary_subject,
self.wrapped_obj.course.tertiary_subject
]
@property
def course_type(self):
seats_types = [seat.type for seat in self.wrapped_obj.seats.all()]
if [Seat.AUDIT] == seats_types:
return Seat.AUDIT
if Seat.CREDIT in seats_types and Seat.VERIFIED in seats_types:
return Seat.CREDIT
if Seat.VERIFIED in seats_types:
return Seat.VERIFIED
if Seat.PROFESSIONAL in seats_types:
return Seat.PROFESSIONAL
return Seat.AUDIT
@property
def organization_key(self):
organizations = self.wrapped_obj.course.organizations.all()
if not organizations:
return None
return organizations[0].key
$(".container a").click(function(event) {
event.preventDefault();
$(this).addClass("selected");
$(this).siblings().removeClass("selected");
var tab = $(this).attr("href");
$(".tab-content").not(tab).css("display", "none");
$(tab).fadeIn();
});
......@@ -6,7 +6,7 @@
// ------------------------------
// #RESET
// ------------------------------
$background-color: palette(grayscale, base) !default;
$background-color: palette(grayscale, base) !default;
// ------------------------------
// #BASE
// ------------------------------
......
......@@ -22,4 +22,5 @@
// #EXTENSIONS
// ------------------------------
@import "base";
@import "publisher/course_form";
@import 'publisher/course_detail';
@import 'publisher/course_form';
// ------------------------------
// // edX Course Discovery: Base
// About: Base resets and definitons (using shared resources from elements when appropriate).
// ------------------------------
// #RESET
// ------------------------------
* {
margin: 0;
padding: 0;
text-decoration: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
color: #434242;
background: #fafafa;
font-family: "Open Sans";
line-height: 1.42857;
}
// ------------------------------
// #BASE
// ------------------------------
html, body {
height: 100%;
margin: 0;
padding: 0;
background: #fafafa;
}
// ------------------------------
// #TYPOGRAPHY
// ------------------------------
.hd-3 {
color: #646262;
font-size: 24px;
font-weight: 400;
margin-bottom: 10px;
}
.container {
width: 1170px;
margin: auto;
overflow: auto;
}
nav {
border-bottom: 2px solid #cacaca;
background-color: #f6f6f6;
font-size: 18px;
font-weight: 600;
.container {
a {
display: inline-block;
padding: 10px;
color: #0ea6ec;
&.selected {
border-bottom: 4px solid #0ea6ec;
color: black;
}
&:first-child {
@include margin-left(30px);
}
}
}
}
#app {
background: #fff;
padding: 0 30px 30px;
}
.course-information {
margin-bottom: 30px;
.info-item {
margin-bottom: 15px;
.heading {
font-weight: bold;
font-size: 16px;
}
}
}
.breadcrumb {
padding: 8px 15px;
list-style: none;
background: white;
border-radius: 3px;
padding-left: 0;
margin: 0 0 1.25rem;
> li {
display: inline-block;
a {
display: inline-block;
border-bottom: 1px solid transparent;
color: #337ab7;
text-decoration: none;
-webkit-transition: color 0.125s ease-in-out 0s, border-color 0.125s ease-in-out 0s;
-moz-transition: color 0.125s ease-in-out 0s, border-color 0.125s ease-in-out 0s;
transition: color 0.125s ease-in-out 0s, border-color 0.125s ease-in-out 0s;
}
+ li:before {
content: " / ";
padding: 0 5px;
color: #ccc;
}
&.active {
color: #777777;
}
}
}
.copy-text {
@include margin-left(5px);
}
.page-header {
padding-bottom: 9px;
margin: 0 0 20px;
border-bottom: 1px solid #eeeeee;
.hd-1 {
margin: 0;
color: black;
font-weight: 600;
}
}
.help-block {
display: block;
margin-top: 5px;
margin-bottom: 10px;
color: #737373;
}
.course-seat {
margin-bottom: 20px;
}
.tab-content {
display: none;
&.active {
display: block;
}
}
.seat-set {
margin-bottom: 20px;
table {
width: 100%;
}
}
......@@ -2,10 +2,10 @@
// // edX Course Discovery: Course form
.course-form {
margin: 20px;
@include margin(20px);
}
.btn-add {
float: right;
margin-right: 30px;
@include float(right);
@include margin-right(30px);
}
......@@ -22,12 +22,14 @@
</script>
{% compress css %}
{% if language_bidi %}
<link rel="stylesheet" href="{% static 'sass/main-rtl.scss' %}" type="text/x-scss">
{% else %}
<link rel="stylesheet" href="{% static 'sass/main-ltr.scss' %}" type="text/x-scss">
{% endif %}
<link rel="stylesheet" href="{% static 'bower_components/pikaday/css/pikaday.css' %}" type="text/x-scss">
{% block stylesheets %}
{% if language_bidi %}
<link rel="stylesheet" href="{% static 'sass/main-rtl.scss' %}" type="text/x-scss">
{% else %}
<link rel="stylesheet" href="{% static 'sass/main-ltr.scss' %}" type="text/x-scss">
{% endif %}
<link rel="stylesheet" href="{% static 'bower_components/pikaday/css/pikaday.css' %}" type="text/x-scss">
{% endblock %}
{% endcompress %}
</head>
......
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Course Run Detail" %}
{% endblock title %}
{% block content %}
<div class="course-information">
<div class="info-item">
<div class="heading">{% trans "Course ID" %}</div>
<div>{{ object.lms_course_id }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Course Type" %}</div>
<div>{{ object.course_type|capfirst }}</div>
</div>
</div>
{% include 'publisher/run_detail/_seats.html' %}
{% include 'publisher/run_detail/_credit_seat.html' %}
{% endblock %}
{% load i18n %}
<h3 class="hd-6 seat-set-hd">{% trans "Credit Seats" %}</h3>
{% if object.credit_seat %}
<div class="seat-set">
<table class="table">
<tr>
<th scope="col">{% trans "Credit Provider" %}</th>
<th scope="col">{% trans "Price" %}</th>
<th scope="col">{% trans "Currency" %}</th>
<th scope="col">{% trans "Credit Hours" %}</th>
<th scope="col">{% trans "Upgrade Deadline" %}</th>
</tr>
<tr>
<td>{{ object.credit_seat.credit_provider}}</td>
<td>{{ object.credit_seat.price}}</td>
<td>{{ object.credit_seat.currency.name}}</td>
<td>{{ object.credit_seat.credit_hours }}</td>
<td>{{ object.credit_seat.upgrade_deadline }}</td>
</tr>
</table>
</div>
{% else %}
{% trans "No Credit Seats Available." %}
{% endif %}
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Course Form" %}
{% endblock title %}
{% block content %}
<div class="course-information">
<div class="info-item">
<div class="heading">{% trans "Title" %}</div>
<div>{{ object.title }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Number" %}</div>
<div>{{ object.number }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Course ID" %}</div>
<div>{{ object.lms_course_id }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Sub Title" %}</div>
<div>{{ object.short_description }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "School" %}</div>
<div>{{ object.organization_key }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Subject" %}</div>
<div>{% for subject in object.subjects %}{{ subject.name }}{% endfor %}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "XSeries" %}</div>
<div>{% if object.is_xseries %}{{ object.xseries_name }}{% endif %}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Start Date" %}</div>
<div>{{ object.start|date:"Y-m-d" }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "End Date" %}</div>
<div>{{ object.end|date:"Y-m-d" }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Self Paced" %}</div>
<div>{{ object.pacing_type }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Staff" %}</div>
<div>{{ object.persons }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Estimated Effort" %}</div>
<div>
{% if object.min_effort and object.max_effort %}
{{ object.min_effort }} {% trans "to" %} {{ object.max_effort }} {% trans "hours per week" %}
{% endif %}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Languages" %}</div>
<div>{{ object.language.name }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Video Translations" %}</div>
<div>{{ object.video_languages }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Level" %}</div>
<div>{{ object.level_type }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "About this Course" %}</div>
<div>{{ object.full_description }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "What you'll learn" %}</div>
<div>{{ object.expected_learnings }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Prerequisite" %}</div>
<div>{{ object.prerequisites }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Keywords" %}</div>
<div>{{ object.wrapped_obj.keywords }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Sponsors" %}</div>
<div>
{% for sponsor in object.wrapped_obj.sponsor.all %}
{{ sponsor.name }}<br>
{% endfor %}
</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Price" %}</div>
<div>{{ object.verified_seat_price }}</div>
</div>
<h3 class="hd-3 de-emphasized">{% trans "Enrollments" %}</h3>
<div class="info-item">
<div class="heading">{% trans "Seats" %}</div>
{% for seat in object.wrapped_obj.seats.all %}
{{ seat.type }} <br>
{% endfor %}
</div>
</div>
{% endblock %}
{% load i18n %}
<h3 class="hd-4 seat-set-hd">Seats</h3>
{% if object.non_credit_seats %}
<div class="seat-set">
<table class="table">
<tr>
<th scope="col">{% trans "Seat Type" %}</th>
<th scope="col">{% trans "Price" %}</th>
<th scope="col">{% trans "Currency" %}</th>
<th scope="col">{% trans "Upgrade Deadline" %}</th>
</tr>
{% for seat in object.non_credit_seats %}
<tr>
<td>{{ seat.type}}</td>
<td>{{ seat.price}}</td>
<td>{{ seat.currency}}</td>
<td>{{ seat.upgrade_deadline }}</td>
</tr>
{% endfor %}
</table>
</div>
{% else %}
{% trans "No Seats Available." %}
{% endif %}
{% extends 'base.html' %}
{% load i18n %}
{% load tz %}
{% block title %}
{% trans "Course Run Detail" %}
{% endblock title %}
{% block content %}
<div class="course-information">
<div class="info-item">
<div class="heading">{% trans "Course Name" %}</div>
<div>{{ object.title }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Organization" %}</div>
<div>{{ object.organization_name }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Number" %}</div>
<div>{{ object.number }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Start Date" %}</div>
<div>{{ object.start|date:"M d, Y, H:i:s A" }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "End Date" %}</div>
<div>{{ object.end|date:"M d, Y, H:i:s A" }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Enrollment Start Date" %}</div>
<div>{{ object.enrollment_start|date:"M d, Y, H:i:s A" }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Enrollment End Date" %}</div>
<div>{{ object.enrollment_end|date:"M d, Y, H:i:s A" }}</div>
</div>
<div class="info-item">
<div class="heading">{% trans "Pacing Type" %}</div>
<div>{{ object.pacing_type }}</div>
</div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% block title %}
{% trans "Course Run Detail" %}
{% endblock title %}
{% block content %}
<nav class="administration-navbar">
<div class="container">
<a class="selected" href="#tab-1">{% trans "All" %}</a>
<a href="#tab-2">{% trans "STUDIO" %}</a>
<a href="#tab-3">{% trans "CAT" %}</a>
<a href="#tab-4">{% trans "DRUPAL" %}</a>
</div>
</nav>
<div id="app" class="container">
<ol class="breadcrumb">
<li><a href="{% url 'publisher:publisher_course_run_detail' pk=object.wrapped_obj.id %}">{% trans "Courses" %}</a></li>
<li class="active">{{ object.title }}</li>
</ol>
<div class="page-header">
<h2 class="hd-2 emphasized">
<span class="course-name">{{ object.title }}</span>
</h2>
</div>
<div class="tab">
<div id="tab-1" class="tab-content active">
{% include 'publisher/run_detail/_studio.html' %}
{% include 'publisher/run_detail/_cat.html' %}
{% include 'publisher/run_detail/_drupal.html' %}
</div>
<div id="tab-2" class="tab-content active">
{% include 'publisher/run_detail/_studio.html' %}
</div>
<div id="tab-3" class="tab-content">
{% include 'publisher/run_detail/_cat.html' %}
</div>
<div id="tab-4" class="tab-content">
{% include 'publisher/run_detail/_drupal.html' %}
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="{% static 'js/publisher/publisher.js' %}"></script>
{% endblock %}
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