Commit 41ec68db by Waheed Ahmed

Create course run from dashboard.

ECOM-7758
parent b08c6361
# pylint: disable=no-member # pylint: disable=no-member
import json import json
from urllib.parse import quote
import ddt import ddt
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
...@@ -20,7 +21,7 @@ from course_discovery.apps.course_metadata.tests.factories import OrganizationFa ...@@ -20,7 +21,7 @@ from course_discovery.apps.course_metadata.tests.factories import OrganizationFa
from course_discovery.apps.ietf_language_tags.models import LanguageTag from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher.api import views from course_discovery.apps.publisher.api import views
from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole
from course_discovery.apps.publisher.constants import INTERNAL_USER_GROUP_NAME from course_discovery.apps.publisher.constants import ADMIN_GROUP_NAME, INTERNAL_USER_GROUP_NAME
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState,
OrganizationExtension, Seat) OrganizationExtension, Seat)
from course_discovery.apps.publisher.tests import JSON_CONTENT_TYPE, factories from course_discovery.apps.publisher.tests import JSON_CONTENT_TYPE, factories
...@@ -825,3 +826,70 @@ class RevertCourseByRevisionTests(TestCase): ...@@ -825,3 +826,70 @@ class RevertCourseByRevisionTests(TestCase):
'publisher:api:course_revision_revert', kwargs={'history_id': revision_id} 'publisher:api:course_revision_revert', kwargs={'history_id': revision_id}
) )
return self.client.put(path=course_revision_path) return self.client.put(path=course_revision_path)
class CoursesAutoCompleteTests(TestCase):
""" Tests for course autocomplete."""
def setUp(self):
super(CoursesAutoCompleteTests, self).setUp()
self.user = UserFactory()
self.course = factories.CourseFactory(title='Test course 1')
self.course2 = factories.CourseFactory(title='Test course 2')
self.organization_extension = factories.OrganizationExtensionFactory()
self.course.organizations.add(self.organization_extension.organization)
self.user.groups.add(self.organization_extension.group)
assign_perm(
OrganizationExtension.VIEW_COURSE, self.organization_extension.group, self.organization_extension
)
self.client.login(username=self.user.username, password=USER_PASSWORD)
self.course_autocomplete_url = reverse('publisher:api:course-autocomplete') + '?q={title}'
def test_course_autocomplete_without_login(self):
""" Verify course autocomplete without login. """
self.client.logout()
self.course_autocomplete_url = self.course_autocomplete_url.format(title='test')
response = self.client.get(self.course_autocomplete_url)
self.assertRedirects(
response,
expected_url='{url}?next={next}'.format(
url=reverse('login'),
next=quote(self.course_autocomplete_url)
),
status_code=302,
target_status_code=302
)
def test_course_autocomplete_with_course_team(self):
""" Verify course autocomplete returns data for course team user. """
response = self.client.get(self.course_autocomplete_url.format(title='test'))
self._assert_response(response, 1)
response = self.client.get(
self.course_autocomplete_url.format(title='dummy')
)
self._assert_response(response, 0)
def test_course_autocomplete_with_admin(self):
""" Verify course autocomplete returns all courses for publisher admin. """
self.user.groups.remove(self.organization_extension.group)
self.user.groups.add(Group.objects.get(name=ADMIN_GROUP_NAME))
response = self.client.get(self.course_autocomplete_url.format(title='test'))
self._assert_response(response, 2)
def test_course_autocomplete_with_internal_user(self):
""" Verify course autocomplete returns all courses for publisher admin. """
self.user.groups.remove(self.organization_extension.group)
self.user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME))
factories.CourseUserRoleFactory(course=self.course2, user=self.user, role=PublisherUserRole.MarketingReviewer)
response = self.client.get(self.course_autocomplete_url.format(title='test'))
self._assert_response(response, 1)
def _assert_response(self, response, expected_length):
""" Assert autocomplete response. """
self.assertEqual(response.status_code, 200)
data = json.loads(response.content.decode('utf-8'))
self.assertEqual(len(data['results']), expected_length)
...@@ -3,8 +3,8 @@ from django.conf.urls import url ...@@ -3,8 +3,8 @@ from django.conf.urls import url
from course_discovery.apps.publisher.api.views import (ChangeCourseRunStateView, ChangeCourseStateView, from course_discovery.apps.publisher.api.views import (ChangeCourseRunStateView, ChangeCourseStateView,
CourseRevisionDetailView, CourseRoleAssignmentView, CourseRevisionDetailView, CourseRoleAssignmentView,
OrganizationGroupUserView, RevertCourseRevisionView, CoursesAutoComplete, OrganizationGroupUserView,
UpdateCourseRunView) RevertCourseRevisionView, UpdateCourseRunView)
urlpatterns = [ urlpatterns = [
url(r'^course_role_assignments/(?P<pk>\d+)/$', CourseRoleAssignmentView.as_view(), name='course_role_assignments'), url(r'^course_role_assignments/(?P<pk>\d+)/$', CourseRoleAssignmentView.as_view(), name='course_role_assignments'),
...@@ -18,4 +18,5 @@ urlpatterns = [ ...@@ -18,4 +18,5 @@ urlpatterns = [
r'^course/revision/(?P<history_id>\d+)/revert/$', r'^course/revision/(?P<history_id>\d+)/revert/$',
RevertCourseRevisionView.as_view(), name='course_revision_revert' RevertCourseRevisionView.as_view(), name='course_revision_revert'
), ),
url(r'^course-autocomplete/$', CoursesAutoComplete.as_view(), name='course-autocomplete'),
] ]
import logging import logging
from dal import autocomplete
from django.apps import apps from django.apps import apps
from django.contrib.auth.mixins import LoginRequiredMixin
from guardian.shortcuts import get_objects_for_user
from rest_framework import status from rest_framework import status
from rest_framework.generics import ListAPIView, RetrieveAPIView, UpdateAPIView, get_object_or_404 from rest_framework.generics import ListAPIView, RetrieveAPIView, UpdateAPIView, get_object_or_404
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
...@@ -16,6 +19,7 @@ from course_discovery.apps.publisher.api.serializers import (CourseRevisionSeria ...@@ -16,6 +19,7 @@ from course_discovery.apps.publisher.api.serializers import (CourseRevisionSeria
from course_discovery.apps.publisher.forms import CustomCourseForm from course_discovery.apps.publisher.forms import CustomCourseForm
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole, from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole,
OrganizationExtension) OrganizationExtension)
from course_discovery.apps.publisher.utils import is_internal_user, is_publisher_admin
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -88,3 +92,28 @@ class RevertCourseRevisionView(APIView): ...@@ -88,3 +92,28 @@ class RevertCourseRevisionView(APIView):
return Response(status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
class CoursesAutoComplete(LoginRequiredMixin, autocomplete.Select2QuerySetView):
""" Course Autocomplete. """
def get_queryset(self):
if self.q:
user = self.request.user
if is_publisher_admin(user):
qs = Course.objects.filter(title__icontains=self.q)
elif is_internal_user(user):
qs = Course.objects.filter(title__icontains=self.q, course_user_roles__user=user).distinct()
else:
organizations = get_objects_for_user(
user,
OrganizationExtension.VIEW_COURSE,
OrganizationExtension,
use_groups=True,
with_superuser=False
).values_list('organization')
qs = Course.objects.filter(title__icontains=self.q, organizations__in=organizations)
return qs
return []
...@@ -192,6 +192,21 @@ class CustomCourseForm(CourseForm): ...@@ -192,6 +192,21 @@ class CustomCourseForm(CourseForm):
self.fields['video_link'].widget = forms.HiddenInput() self.fields['video_link'].widget = forms.HiddenInput()
class CourseSearchForm(forms.Form):
""" Course Type ahead Search Form. """
course = forms.ModelChoiceField(
label=_('Find Course By Title'),
queryset=Course.objects.all(),
widget=autocomplete.ModelSelect2(
url='publisher:api:course-autocomplete',
attrs={
'data-minimum-input-length': 3,
}
),
required=True,
)
class CourseRunForm(BaseCourseForm): class CourseRunForm(BaseCourseForm):
""" Course Run Form. """ """ Course Run Form. """
......
...@@ -2764,3 +2764,97 @@ class CourseRevisionViewTests(TestCase): ...@@ -2764,3 +2764,97 @@ class CourseRevisionViewTests(TestCase):
kwargs={'pk': course_id, 'revision_id': revision_id}) kwargs={'pk': course_id, 'revision_id': revision_id})
return self.client.get(path=revision_path) return self.client.get(path=revision_path)
class CreateRunFromDashboardViewTests(TestCase):
""" Tests for the publisher `CreateRunFromDashboardView`. """
def setUp(self):
super(CreateRunFromDashboardViewTests, self).setUp()
self.user = UserFactory()
self.course = factories.CourseFactory()
factories.CourseStateFactory(course=self.course)
factories.CourseUserRoleFactory.create(course=self.course, role=PublisherUserRole.CourseTeam, user=self.user)
self.organization_extension = factories.OrganizationExtensionFactory()
self.course.organizations.add(self.organization_extension.organization)
self.user.groups.add(self.organization_extension.group)
assign_perm(
OrganizationExtension.VIEW_COURSE_RUN, self.organization_extension.group, self.organization_extension
)
self.client.login(username=self.user.username, password=USER_PASSWORD)
self.create_course_run_url = reverse('publisher:publisher_create_run_from_dashboard')
def test_courserun_form_without_login(self):
""" Verify that user can't access new course run form page when not logged in. """
self.client.logout()
response = self.client.get(self.create_course_run_url)
self.assertRedirects(
response,
expected_url='{url}?next={next}'.format(
url=reverse('login'),
next=self.create_course_run_url
),
status_code=302,
target_status_code=302
)
self.client.login(username=self.user.username, password=USER_PASSWORD)
response = self.client.get(self.create_course_run_url)
self.assertEqual(response.status_code, 200)
def _post_data(self):
return {
'course': self.course.id,
'start': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'end': (datetime.now() + timedelta(days=60)).strftime('%Y-%m-%d %H:%M:%S'),
'pacing_type': 'self_paced',
'type': Seat.VERIFIED,
'price': 450
}
def test_create_course_run_and_seat_without_parent_course(self):
""" Verify that user cannot create course run without selecting parent course.
"""
post_data = self._post_data()
post_data.pop('course')
response = self.client.post(self.create_course_run_url, post_data)
self.assertContains(response, 'Please fill all required fields.', status_code=400)
def test_create_course_run_and_seat(self):
""" Verify that we can create a new course run with seat. """
self.assertEqual(self.course.course_runs.count(), 0)
new_user = factories.UserFactory()
new_user.groups.add(self.organization_extension.group)
factories.CourseUserRoleFactory.create(
course=self.course, role=PublisherUserRole.ProjectCoordinator, user=factories.UserFactory()
)
self.assertEqual(self.course.course_team_admin, self.user)
post_data = self._post_data()
response = self.client.post(self.create_course_run_url, self._post_data())
self.assertEqual(self.course.course_runs.count(), 1)
new_seat = Seat.objects.get(type=post_data['type'], price=post_data['price'])
self.assertRedirects(
response,
expected_url=reverse('publisher:publisher_course_run_detail', kwargs={'pk': new_seat.course_run.id}),
status_code=302,
target_status_code=200
)
self.assertEqual(new_seat.type, Seat.VERIFIED)
self.assertEqual(new_seat.price, post_data['price'])
# Verify that and email is sent for studio instance request to project coordinator.
self.assertEqual(len(mail.outbox), 1)
self.assertEqual([self.course.project_coordinator.email], mail.outbox[0].to)
expected_subject = 'New Studio instance request for {title}'.format(title=self.course.title)
self.assertEqual(str(mail.outbox[0].subject), expected_subject)
...@@ -20,6 +20,12 @@ urlpatterns = [ ...@@ -20,6 +20,12 @@ urlpatterns = [
url(r'^course_runs/(?P<pk>\d+)/$', views.CourseRunDetailView.as_view(), name='publisher_course_run_detail'), url(r'^course_runs/(?P<pk>\d+)/$', views.CourseRunDetailView.as_view(), name='publisher_course_run_detail'),
url(r'^course_runs/(?P<pk>\d+)/edit/$', views.CourseRunEditView.as_view(), name='publisher_course_runs_edit'), url(r'^course_runs/(?P<pk>\d+)/edit/$', views.CourseRunEditView.as_view(), name='publisher_course_runs_edit'),
url( url(
r'^course_runs/new/$',
views.CreateRunFromDashboardView.as_view(),
name='publisher_create_run_from_dashboard'
),
url(
r'^user/toggle/email_settings/$', r'^user/toggle/email_settings/$',
views.ToggleEmailNotification.as_view(), views.ToggleEmailNotification.as_view(),
name='publisher_toggle_email_settings' name='publisher_toggle_email_settings'
......
...@@ -24,7 +24,8 @@ from course_discovery.apps.course_metadata.models import Person ...@@ -24,7 +24,8 @@ from course_discovery.apps.course_metadata.models import Person
from course_discovery.apps.ietf_language_tags.models import LanguageTag from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher import emails, mixins from course_discovery.apps.publisher import emails, mixins
from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole
from course_discovery.apps.publisher.forms import CustomCourseForm, CustomCourseRunForm, CustomSeatForm from course_discovery.apps.publisher.forms import (CourseSearchForm, CustomCourseForm, CustomCourseRunForm,
CustomSeatForm)
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole, from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole,
OrganizationExtension, Seat, UserAttributes) OrganizationExtension, Seat, UserAttributes)
from course_discovery.apps.publisher.utils import (get_internal_users, has_role_for_course, is_internal_user, from course_discovery.apps.publisher.utils import (get_internal_users, has_role_for_course, is_internal_user,
...@@ -565,6 +566,39 @@ class CreateCourseRunView(mixins.LoginRequiredMixin, CreateView): ...@@ -565,6 +566,39 @@ class CreateCourseRunView(mixins.LoginRequiredMixin, CreateView):
return render(request, self.template_name, context, status=400) return render(request, self.template_name, context, status=400)
class CreateRunFromDashboardView(CreateCourseRunView):
""" Create Course Run From Dashboard With Type ahead Search For Parent Course."""
course_form = CourseSearchForm
def get_context_data(self, **kwargs):
context = {
'from_dashboard': True,
'course_form': self.course_form(),
'run_form': self.run_form(),
'seat_form': self.seat_form()
}
return context
def post(self, request, *args, **kwargs):
course_form = self.course_form(request.POST)
run_form = self.run_form(request.POST)
seat_form = self.seat_form(request.POST)
if course_form.is_valid() and run_form.is_valid() and seat_form.is_valid():
self.parent_course = course_form.cleaned_data.get('course')
return super(CreateRunFromDashboardView, self).post(request, *args, **kwargs)
messages.error(request, _('Please fill all required fields.'))
context = self.get_context_data()
context.update(
{
'course_form': course_form,
'run_form': run_form,
'seat_form': seat_form,
}
)
return render(request, self.template_name, context, status=400)
class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMixin, UpdateView): class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMixin, UpdateView):
""" Course Run Edit View.""" """ Course Run Edit View."""
model = CourseRun model = CourseRun
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-09 15:18+0500\n" "POT-Creation-Date: 2017-05-09 17:22+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -616,6 +616,10 @@ msgid "Syllabus" ...@@ -616,6 +616,10 @@ msgid "Syllabus"
msgstr "" msgstr ""
#: apps/publisher/forms.py #: apps/publisher/forms.py
msgid "Find Course By Title"
msgstr ""
#: apps/publisher/forms.py
msgid "Course Start Date" msgid "Course Start Date"
msgstr "" msgstr ""
...@@ -1415,6 +1419,18 @@ msgid "" ...@@ -1415,6 +1419,18 @@ msgid ""
msgstr "" msgstr ""
#: templates/publisher/add_courserun_form.html #: templates/publisher/add_courserun_form.html
msgid "FIND COURSE BY TITLE"
msgstr ""
#: templates/publisher/add_courserun_form.html
#, python-format
msgid ""
"\n"
" Find the course that you are creating a run for by typing in the title. If you don't find a match, please check that the name is correct or %(link_start)s%(new_course_url)s%(link_middle)screate a new course%(link_end)s.\n"
" "
msgstr ""
#: templates/publisher/add_courserun_form.html
#: templates/publisher/course_run/edit_run_form.html #: templates/publisher/course_run/edit_run_form.html
msgid "COURSE START DATE" msgid "COURSE START DATE"
msgstr "" msgstr ""
...@@ -2494,6 +2510,10 @@ msgid "Add a New Course" ...@@ -2494,6 +2510,10 @@ msgid "Add a New Course"
msgstr "" msgstr ""
#: templates/publisher/dashboard.html #: templates/publisher/dashboard.html
msgid "Add a Course Run"
msgstr ""
#: templates/publisher/dashboard.html
msgid "" msgid ""
"EdX Publisher is a companion to edX Studio. Course teams enter About page " "EdX Publisher is a companion to edX Studio. Course teams enter About page "
"information in Publisher, and course content in Studio." "information in Publisher, and course content in Studio."
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-09 15:18+0500\n" "POT-Creation-Date: 2017-05-09 17:22+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-09 15:18+0500\n" "POT-Creation-Date: 2017-05-09 17:22+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -742,6 +742,10 @@ msgid "Syllabus" ...@@ -742,6 +742,10 @@ msgid "Syllabus"
msgstr "Sýlläßüs Ⱡ'σяєм ιρѕυм ∂#" msgstr "Sýlläßüs Ⱡ'σяєм ιρѕυм ∂#"
#: apps/publisher/forms.py #: apps/publisher/forms.py
msgid "Find Course By Title"
msgstr "Fïnd Çöürsé Bý Tïtlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: apps/publisher/forms.py
msgid "Course Start Date" msgid "Course Start Date"
msgstr "Çöürsé Stärt Däté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" msgstr "Çöürsé Stärt Däté Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
...@@ -1631,6 +1635,21 @@ msgstr "" ...@@ -1631,6 +1635,21 @@ msgstr ""
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє#" " Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє#"
#: templates/publisher/add_courserun_form.html #: templates/publisher/add_courserun_form.html
msgid "FIND COURSE BY TITLE"
msgstr "FÌND ÇÖÛRSÉ BÝ TÌTLÉ Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: templates/publisher/add_courserun_form.html
#, python-format
msgid ""
"\n"
" Find the course that you are creating a run for by typing in the title. If you don't find a match, please check that the name is correct or %(link_start)s%(new_course_url)s%(link_middle)screate a new course%(link_end)s.\n"
" "
msgstr ""
"\n"
" Fïnd thé çöürsé thät ýöü äré çréätïng ä rün för ßý týpïng ïn thé tïtlé. Ìf ýöü dön't fïnd ä mätçh, pléäsé çhéçk thät thé nämé ïs çörréçt ör %(link_start)s%(new_course_url)s%(link_middle)sçréäté ä néw çöürsé%(link_end)s.\n"
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє#"
#: templates/publisher/add_courserun_form.html
#: templates/publisher/course_run/edit_run_form.html #: templates/publisher/course_run/edit_run_form.html
msgid "COURSE START DATE" msgid "COURSE START DATE"
msgstr "ÇÖÛRSÉ STÀRT DÀTÉ Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#" msgstr "ÇÖÛRSÉ STÀRT DÀTÉ Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
...@@ -2940,6 +2959,10 @@ msgid "Add a New Course" ...@@ -2940,6 +2959,10 @@ msgid "Add a New Course"
msgstr "Àdd ä Néw Çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" msgstr "Àdd ä Néw Çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: templates/publisher/dashboard.html #: templates/publisher/dashboard.html
msgid "Add a Course Run"
msgstr "Àdd ä Çöürsé Rün Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
#: templates/publisher/dashboard.html
msgid "" msgid ""
"EdX Publisher is a companion to edX Studio. Course teams enter About page " "EdX Publisher is a companion to edX Studio. Course teams enter About page "
"information in Publisher, and course content in Studio." "information in Publisher, and course content in Studio."
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-09 15:18+0500\n" "POT-Creation-Date: 2017-05-09 17:22+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
......
...@@ -116,3 +116,16 @@ $btn-filter-color: rgba(228, 228, 228, 1); ...@@ -116,3 +116,16 @@ $btn-filter-color: rgba(228, 228, 228, 1);
border-radius: 8px; border-radius: 8px;
} }
.btn-add-course {
background-color: #34495E;
border: solid 1px #243342;
color: #F5F9FD;
font-size: 16px;
}
.btn-add-courserun {
background-color: #00A0E3;
border: solid 1px #0491CB;
color: #F5F9FD;
font-size: 16px;
}
...@@ -179,3 +179,7 @@ ...@@ -179,3 +179,7 @@
@include text-align(right); @include text-align(right);
width: 100%; width: 100%;
} }
.error-text {
color: #b20610;
}
...@@ -435,15 +435,8 @@ ...@@ -435,15 +435,8 @@
display: inline-block; display: inline-block;
} }
.btn-add-course {
background-color: #34495E;
border: solid 1px #243342;
color: #F5F9FD;
font-size: 16px;
}
.about-publisher { .about-publisher {
max-width: 75%; max-width: 60%;
} }
.about-and-button { .about-and-button {
......
...@@ -30,6 +30,30 @@ ...@@ -30,6 +30,30 @@
<div class="course-form"> <div class="course-form">
<div class="course-information"> <div class="course-information">
<fieldset class="form-group grid-container grid-manual"> <fieldset class="form-group grid-container grid-manual">
{% if from_dashboard %}
<div class="field-title">{% trans "FIND COURSE BY TITLE" %}</div>
<div class="row">
<div class="col col-6 help-text">
<p>
{% url 'publisher:publisher_courses_new' as new_course_url %}
{% blocktrans with link_start='<a href="' link_middle='">' link_end='</a>' %}
Find the course that you are creating a run for by typing in the title. If you don't find a match, please check that the name is correct or {{ link_start }}{{ new_course_url }}{{ link_middle }}create a new course{{ link_end }}.
{% endblocktrans%}
</p>
</div>
<div class="col col-6">
<label class="field-label ">
{{ course_form.course.label }}
<span class="required">*</span>
</label>
{{ course_form.course }}
{% if course_form.course.errors %}
<div class="error-text">{{ course_form.course.errors.as_text }}</div>
{% endif %}
</div>
</div>
{% endif %}
<div class="field-title">{% trans "COURSE START DATE" %}</div> <div class="field-title">{% trans "COURSE START DATE" %}</div>
<div class="row"> <div class="row">
<div class="col col-6 help-text"> <div class="col col-6 help-text">
...@@ -127,8 +151,10 @@ ...@@ -127,8 +151,10 @@
{% endblock %} {% endblock %}
{% block extra_js %} {% block extra_js %}
<script src="{% static 'js/publisher/organizations.js' %}"></script>
<script src="{% static 'js/publisher/course-tabs.js' %}"></script> <script src="{% static 'js/publisher/course-tabs.js' %}"></script>
<script src="{% static 'js/publisher/seat-type-change.js' %}"></script> <script src="{% static 'js/publisher/seat-type-change.js' %}"></script>
<script src="{% static 'js/publisher/change-admin.js' %}"></script> {% endblock %}
{% block js_without_compress %}
{{ course_form.media }}
{% endblock %} {% endblock %}
...@@ -14,10 +14,13 @@ ...@@ -14,10 +14,13 @@
<a href="{% url 'publisher:publisher_courses_new' %}" class="btn btn-brand btn-add-course"> <a href="{% url 'publisher:publisher_courses_new' %}" class="btn btn-brand btn-add-course">
{% trans "Add a New Course" %} {% trans "Add a New Course" %}
</a> </a>
<a href="{% url 'publisher:publisher_create_run_from_dashboard' %}" class="btn btn-brand btn-add-courserun">
{% trans "Add a Course Run" %}
</a>
</div> </div>
<p>{% trans "EdX Publisher is a companion to edX Studio. Course teams enter About page information in Publisher, and course content in Studio." %}</p> <p>{% trans "EdX Publisher is a companion to edX Studio. Course teams enter About page information in Publisher, and course content in Studio." %}</p>
{% with studio_count=studio_request_courses|length published_count=published_course_runs|length preview_count=preview_course_runs|length in_progress_count=in_progress_course_runs|length %} {% with studio_count=studio_request_courses|length published_count=published_course_runs|length preview_count=preview_course_runs|length in_progress_count=in_progress_course_runs|length %}
<h2 class="hd-2 emphasized">{% trans "Course runs" %}</h2> <h2 class="hd-2 emphasized course-runs-heading">{% trans "Course runs" %}</h2>
<ul role="tablist" class="tabs"> <ul role="tablist" class="tabs">
<li role="tab" id="tab-progress" class="tab" aria-selected="true" aria-expanded="false" <li role="tab" id="tab-progress" class="tab" aria-selected="true" aria-expanded="false"
aria-controls="progress" tabindex="0"> aria-controls="progress" tabindex="0">
......
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