Commit 7f691e4a by cewing

MIT: CCX. Rename POC to CCX

Final official name is Custom Courses for EdX (CCX), rename all code to remove previous name.

Rename the FEATURE constant used to identify this feature

Rename the middleware for the CCX change

rename the constant used for storing the current poc id on the session.

rename the _PocContext threading local

rename the override provider in all places where it is referenced

`PersonalOnlineCoursesOverrideProvider` -> `CustomCoursesForEdxOverrideProvider`

generally rename symbols from overrides.py to replace `poc` with `ccx` where possible without changing model names or attributes

rename more symbols from poc to ccx
rename util functions from app utils module

general symbol renaming poc -> ccx in views.py and related url changes

Rename the coach role wherever it is used.

reword poc_coach to ccx_coach

UI rename

replace POC with CCX globally

template context variable renamed

rename poc_ to ccx_ in urls and all related locations (views, js, scss etc)

remove pocs migrations

Final massive renaming, including models.  Re-built migration.

cleaning up a few tailing references

Fix reference typo in schedule template JS

undo modifications made on the fly in test setup to ensure that our tests are properly isolated from the rest of the system tests.

Fixes jazkarta/edx-platform#38

Clean up some leftover strings and comments

fixing more strings and comments in python files

fix a naming error in the schedule tab that was causing problems in deleting courseware items.

Fixes jazkarta/edx-platform#36

updating tests and utility code to match changes in infrastructure from latest rebase
parent fbaab967
...@@ -267,12 +267,12 @@ class LibraryUserRole(CourseRole): ...@@ -267,12 +267,12 @@ class LibraryUserRole(CourseRole):
super(LibraryUserRole, self).__init__(self.ROLE, *args, **kwargs) super(LibraryUserRole, self).__init__(self.ROLE, *args, **kwargs)
class CoursePocCoachRole(CourseRole): class CourseCcxCoachRole(CourseRole):
"""A POC Coach""" """A CCX Coach"""
ROLE = 'poc_coach' ROLE = 'ccx_coach'
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CoursePocCoachRole, self).__init__(self.ROLE, *args, **kwargs) super(CourseCcxCoachRole, self).__init__(self.ROLE, *args, **kwargs)
class OrgStaffRole(OrgRole): class OrgStaffRole(OrgRole):
......
...@@ -660,16 +660,16 @@ def dashboard(request): ...@@ -660,16 +660,16 @@ def dashboard(request):
if course.pre_requisite_courses) if course.pre_requisite_courses)
courses_requirements_not_met = get_pre_requisite_courses_not_completed(user, courses_having_prerequisites) courses_requirements_not_met = get_pre_requisite_courses_not_completed(user, courses_having_prerequisites)
poc_membership_triplets = [] ccx_membership_triplets = []
if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False): if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
from pocs import ACTIVE_POC_KEY from ccx import ACTIVE_CCX_KEY
from pocs.utils import get_poc_membership_triplets from ccx.utils import get_ccx_membership_triplets
poc_membership_triplets = get_poc_membership_triplets( ccx_membership_triplets = get_ccx_membership_triplets(
user, course_org_filter, org_filter_out_set user, course_org_filter, org_filter_out_set
) )
# should we deselect any active POC at this time so that we don't have # should we deselect any active CCX at this time so that we don't have
# to change the URL for viewing a course? I think so. # to change the URL for viewing a course? I think so.
request.session[ACTIVE_POC_KEY] = None request.session[ACTIVE_CCX_KEY] = None
context = { context = {
'enrollment_message': enrollment_message, 'enrollment_message': enrollment_message,
...@@ -702,7 +702,7 @@ def dashboard(request): ...@@ -702,7 +702,7 @@ def dashboard(request):
'provider_states': [], 'provider_states': [],
'order_history_list': order_history_list, 'order_history_list': order_history_list,
'courses_requirements_not_met': courses_requirements_not_met, 'courses_requirements_not_met': courses_requirements_not_met,
'poc_membership_triplets': poc_membership_triplets, 'ccx_membership_triplets': ccx_membership_triplets,
} }
if third_party_auth.is_enabled(): if third_party_auth.is_enabled():
...@@ -1818,15 +1818,15 @@ def activate_account(request, key): ...@@ -1818,15 +1818,15 @@ def activate_account(request, key):
if cea.auto_enroll: if cea.auto_enroll:
CourseEnrollment.enroll(student[0], cea.course_id) CourseEnrollment.enroll(student[0], cea.course_id)
# enroll student in any pending POCs he/she may have if auto_enroll flag is set # enroll student in any pending CCXs he/she may have if auto_enroll flag is set
if settings.FEATURES.get('PERSONAL_ONLINE_COURSES'): if settings.FEATURES.get('CUSTOM_COURSES_EDX'):
from pocs.models import PocMembership, PocFutureMembership from ccx.models import CcxMembership, CcxFutureMembership
pfms = PocFutureMembership.objects.filter( pfms = CcxFutureMembership.objects.filter(
email=student[0].email email=student[0].email
) )
for pfm in pfms: for pfm in pfms:
if pfm.auto_enroll: if pfm.auto_enroll:
PocMembership.auto_enroll(student[0], pfm) CcxMembership.auto_enroll(student[0], pfm)
resp = render_to_response( resp = render_to_response(
"registration/activation_complete.html", "registration/activation_complete.html",
......
...@@ -193,7 +193,7 @@ class CourseTab(object): ...@@ -193,7 +193,7 @@ class CourseTab(object):
'edxnotes': EdxNotesTab, 'edxnotes': EdxNotesTab,
'syllabus': SyllabusTab, 'syllabus': SyllabusTab,
'instructor': InstructorTab, # not persisted 'instructor': InstructorTab, # not persisted
'poc_coach': PocCoachTab, # not persisted 'ccx_coach': CcxCoachTab, # not persisted
} }
tab_type = tab_dict.get('type') tab_type = tab_dict.get('type')
...@@ -376,9 +376,9 @@ class DiscussionTab(EnrolledOrStaffTab): ...@@ -376,9 +376,9 @@ class DiscussionTab(EnrolledOrStaffTab):
) )
def can_display(self, course, settings, is_user_authenticated, is_user_staff, is_user_enrolled): def can_display(self, course, settings, is_user_authenticated, is_user_staff, is_user_enrolled):
if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False): if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
from pocs.overrides import get_current_poc from ccx.overrides import get_current_ccx
if get_current_poc(): if get_current_ccx():
return False return False
super_can_display = super(DiscussionTab, self).can_display( super_can_display = super(DiscussionTab, self).can_display(
course, settings, is_user_authenticated, is_user_staff, is_user_enrolled course, settings, is_user_authenticated, is_user_staff, is_user_enrolled
...@@ -738,26 +738,26 @@ class InstructorTab(StaffTab): ...@@ -738,26 +738,26 @@ class InstructorTab(StaffTab):
) )
class PocCoachTab(CourseTab): class CcxCoachTab(CourseTab):
""" """
A tab for the personal online course coaches. A tab for the custom course coaches.
""" """
type = 'poc_coach' type = 'ccx_coach'
def __init__(self, tab_dict=None): # pylint: disable=unused-argument def __init__(self, tab_dict=None): # pylint: disable=unused-argument
super(PocCoachTab, self).__init__( super(CcxCoachTab, self).__init__(
name=_('POC Coach'), name=_('CCX Coach'),
tab_id=self.type, tab_id=self.type,
link_func=link_reverse_func('poc_coach_dashboard'), link_func=link_reverse_func('ccx_coach_dashboard'),
) )
def can_display(self, course, settings, *args, **kw): def can_display(self, course, settings, *args, **kw):
# TODO Check that user actually has 'poc_coach' role on course # TODO Check that user actually has 'ccx_coach' role on course
# this is difficult to do because the user isn't passed in. # this is difficult to do because the user isn't passed in.
# We need either a hack or an architectural realignment. # We need either a hack or an architectural realignment.
return ( return (
settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False) and settings.FEATURES.get('CUSTOM_COURSES_EDX', False) and
super(PocCoachTab, self).can_display(course, settings, *args, **kw)) super(CcxCoachTab, self).can_display(course, settings, *args, **kw))
class CourseTabList(List): class CourseTabList(List):
...@@ -860,9 +860,9 @@ class CourseTabList(List): ...@@ -860,9 +860,9 @@ class CourseTabList(List):
instructor_tab = InstructorTab() instructor_tab = InstructorTab()
if instructor_tab.can_display(course, settings, is_user_authenticated, is_user_staff, is_user_enrolled): if instructor_tab.can_display(course, settings, is_user_authenticated, is_user_staff, is_user_enrolled):
yield instructor_tab yield instructor_tab
poc_coach_tab = PocCoachTab() ccx_coach_tab = CcxCoachTab()
if poc_coach_tab.can_display(course, settings, is_user_authenticated, is_user_staff, is_user_enrolled): if ccx_coach_tab.can_display(course, settings, is_user_authenticated, is_user_staff, is_user_enrolled):
yield poc_coach_tab yield ccx_coach_tab
@staticmethod @staticmethod
def iterate_displayable_cms( def iterate_displayable_cms(
......
ACTIVE_CCX_KEY = '_ccx_id'
...@@ -8,49 +8,62 @@ from django.db import models ...@@ -8,49 +8,62 @@ from django.db import models
class Migration(SchemaMigration): class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding model 'PersonalOnlineCourse' # Adding model 'CustomCourseForEdX'
db.create_table('pocs_personalonlinecourse', ( db.create_table('ccx_customcourseforedx', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('course_id', self.gf('xmodule_django.models.CourseKeyField')(max_length=255, db_index=True)), ('course_id', self.gf('xmodule_django.models.CourseKeyField')(max_length=255, db_index=True)),
('display_name', self.gf('django.db.models.fields.CharField')(max_length=255)), ('display_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
('coach', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), ('coach', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
)) ))
db.send_create_signal('pocs', ['PersonalOnlineCourse']) db.send_create_signal('ccx', ['CustomCourseForEdX'])
# Adding model 'PocMembership' # Adding model 'CcxMembership'
db.create_table('pocs_pocmembership', ( db.create_table('ccx_ccxmembership', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('poc', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['pocs.PersonalOnlineCourse'])), ('ccx', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ccx.CustomCourseForEdX'])),
('student', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), ('student', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('active', self.gf('django.db.models.fields.BooleanField')(default=False)),
)) ))
db.send_create_signal('pocs', ['PocMembership']) db.send_create_signal('ccx', ['CcxMembership'])
# Adding model 'PocFieldOverride' # Adding model 'CcxFutureMembership'
db.create_table('pocs_pocfieldoverride', ( db.create_table('ccx_ccxfuturemembership', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('poc', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['pocs.PersonalOnlineCourse'])), ('ccx', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ccx.CustomCourseForEdX'])),
('email', self.gf('django.db.models.fields.CharField')(max_length=255)),
('auto_enroll', self.gf('django.db.models.fields.BooleanField')(default=False)),
))
db.send_create_signal('ccx', ['CcxFutureMembership'])
# Adding model 'CcxFieldOverride'
db.create_table('ccx_ccxfieldoverride', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('ccx', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ccx.CustomCourseForEdX'])),
('location', self.gf('xmodule_django.models.LocationKeyField')(max_length=255, db_index=True)), ('location', self.gf('xmodule_django.models.LocationKeyField')(max_length=255, db_index=True)),
('field', self.gf('django.db.models.fields.CharField')(max_length=255)), ('field', self.gf('django.db.models.fields.CharField')(max_length=255)),
('value', self.gf('django.db.models.fields.TextField')(default='null')), ('value', self.gf('django.db.models.fields.TextField')(default='null')),
)) ))
db.send_create_signal('pocs', ['PocFieldOverride']) db.send_create_signal('ccx', ['CcxFieldOverride'])
# Adding unique constraint on 'PocFieldOverride', fields ['poc', 'location', 'field'] # Adding unique constraint on 'CcxFieldOverride', fields ['ccx', 'location', 'field']
db.create_unique('pocs_pocfieldoverride', ['poc_id', 'location', 'field']) db.create_unique('ccx_ccxfieldoverride', ['ccx_id', 'location', 'field'])
def backwards(self, orm): def backwards(self, orm):
# Removing unique constraint on 'PocFieldOverride', fields ['poc', 'location', 'field'] # Removing unique constraint on 'CcxFieldOverride', fields ['ccx', 'location', 'field']
db.delete_unique('pocs_pocfieldoverride', ['poc_id', 'location', 'field']) db.delete_unique('ccx_ccxfieldoverride', ['ccx_id', 'location', 'field'])
# Deleting model 'CustomCourseForEdX'
db.delete_table('ccx_customcourseforedx')
# Deleting model 'PersonalOnlineCourse' # Deleting model 'CcxMembership'
db.delete_table('pocs_personalonlinecourse') db.delete_table('ccx_ccxmembership')
# Deleting model 'PocMembership' # Deleting model 'CcxFutureMembership'
db.delete_table('pocs_pocmembership') db.delete_table('ccx_ccxfuturemembership')
# Deleting model 'PocFieldOverride' # Deleting model 'CcxFieldOverride'
db.delete_table('pocs_pocfieldoverride') db.delete_table('ccx_ccxfieldoverride')
models = { models = {
...@@ -83,34 +96,42 @@ class Migration(SchemaMigration): ...@@ -83,34 +96,42 @@ class Migration(SchemaMigration):
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
}, },
'contenttypes.contenttype': { 'ccx.ccxfieldoverride': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'Meta': {'unique_together': "(('ccx', 'location', 'field'),)", 'object_name': 'CcxFieldOverride'},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'ccx': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ccx.CustomCourseForEdX']"}),
'field': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'location': ('xmodule_django.models.LocationKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 'value': ('django.db.models.fields.TextField', [], {'default': "'null'"})
},
'ccx.ccxfuturemembership': {
'Meta': {'object_name': 'CcxFutureMembership'},
'auto_enroll': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'ccx': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ccx.CustomCourseForEdX']"}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}, },
'pocs.personalonlinecourse': { 'ccx.ccxmembership': {
'Meta': {'object_name': 'PersonalOnlineCourse'}, 'Meta': {'object_name': 'CcxMembership'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'ccx': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ccx.CustomCourseForEdX']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'student': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'ccx.customcourseforedx': {
'Meta': {'object_name': 'CustomCourseForEdX'},
'coach': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), 'coach': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}), 'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}, },
'pocs.pocfieldoverride': { 'contenttypes.contenttype': {
'Meta': {'unique_together': "(('poc', 'location', 'field'),)", 'object_name': 'PocFieldOverride'}, 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'field': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location': ('xmodule_django.models.LocationKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"}),
'value': ('django.db.models.fields.TextField', [], {'default': "'null'"})
},
'pocs.pocmembership': {
'Meta': {'object_name': 'PocMembership'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'student': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
} }
} }
complete_apps = ['pocs'] complete_apps = ['ccx']
\ No newline at end of file \ No newline at end of file
...@@ -5,20 +5,20 @@ from student.models import CourseEnrollment, AlreadyEnrolledError ...@@ -5,20 +5,20 @@ from student.models import CourseEnrollment, AlreadyEnrolledError
from xmodule_django.models import CourseKeyField, LocationKeyField from xmodule_django.models import CourseKeyField, LocationKeyField
class PersonalOnlineCourse(models.Model): class CustomCourseForEdX(models.Model):
""" """
A Personal Online Course. A Custom Course.
""" """
course_id = CourseKeyField(max_length=255, db_index=True) course_id = CourseKeyField(max_length=255, db_index=True)
display_name = models.CharField(max_length=255) display_name = models.CharField(max_length=255)
coach = models.ForeignKey(User, db_index=True) coach = models.ForeignKey(User, db_index=True)
class PocMembership(models.Model): class CcxMembership(models.Model):
""" """
Which students are in a POC? Which students are in a CCX?
""" """
poc = models.ForeignKey(PersonalOnlineCourse, db_index=True) ccx = models.ForeignKey(CustomCourseForEdX, db_index=True)
student = models.ForeignKey(User, db_index=True) student = models.ForeignKey(User, db_index=True)
active = models.BooleanField(default=False) active = models.BooleanField(default=False)
...@@ -30,11 +30,11 @@ class PocMembership(models.Model): ...@@ -30,11 +30,11 @@ class PocMembership(models.Model):
msg = "auto enrollment not allowed for {}" msg = "auto enrollment not allowed for {}"
raise ValueError(msg.format(future_membership)) raise ValueError(msg.format(future_membership))
membership = cls( membership = cls(
poc=future_membership.poc, student=student, active=True ccx=future_membership.ccx, student=student, active=True
) )
try: try:
CourseEnrollment.enroll( CourseEnrollment.enroll(
student, future_membership.poc.course_id, check_access=True student, future_membership.ccx.course_id, check_access=True
) )
except AlreadyEnrolledError: except AlreadyEnrolledError:
# if the user is already enrolled in the course, great! # if the user is already enrolled in the course, great!
...@@ -48,24 +48,24 @@ class PocMembership(models.Model): ...@@ -48,24 +48,24 @@ class PocMembership(models.Model):
return cls.objects.filter(student=user, active__exact=active) return cls.objects.filter(student=user, active__exact=active)
class PocFutureMembership(models.Model): class CcxFutureMembership(models.Model):
""" """
Which emails for non-users are waiting to be added to POC on registration Which emails for non-users are waiting to be added to CCX on registration
""" """
poc = models.ForeignKey(PersonalOnlineCourse, db_index=True) ccx = models.ForeignKey(CustomCourseForEdX, db_index=True)
email = models.CharField(max_length=255) email = models.CharField(max_length=255)
auto_enroll = models.BooleanField(default=0) auto_enroll = models.BooleanField(default=0)
class PocFieldOverride(models.Model): class CcxFieldOverride(models.Model):
""" """
Field overrides for personal online courses. Field overrides for custom courses.
""" """
poc = models.ForeignKey(PersonalOnlineCourse, db_index=True) ccx = models.ForeignKey(CustomCourseForEdX, db_index=True)
location = LocationKeyField(max_length=255, db_index=True) location = LocationKeyField(max_length=255, db_index=True)
field = models.CharField(max_length=255) field = models.CharField(max_length=255)
class Meta: class Meta:
unique_together = (('poc', 'location', 'field'),) unique_together = (('ccx', 'location', 'field'),)
value = models.TextField(default='null') value = models.TextField(default='null')
...@@ -8,81 +8,81 @@ import threading ...@@ -8,81 +8,81 @@ import threading
from contextlib import contextmanager from contextlib import contextmanager
from courseware.field_overrides import FieldOverrideProvider from courseware.field_overrides import FieldOverrideProvider
from pocs import ACTIVE_POC_KEY from ccx import ACTIVE_CCX_KEY
from .models import PocMembership, PocFieldOverride from .models import CcxMembership, CcxFieldOverride
class PersonalOnlineCoursesOverrideProvider(FieldOverrideProvider): class CustomCoursesForEdxOverrideProvider(FieldOverrideProvider):
""" """
A concrete implementation of A concrete implementation of
:class:`~courseware.field_overrides.FieldOverrideProvider` which allows for :class:`~courseware.field_overrides.FieldOverrideProvider` which allows for
overrides to be made on a per user basis. overrides to be made on a per user basis.
""" """
def get(self, block, name, default): def get(self, block, name, default):
poc = get_current_poc() ccx = get_current_ccx()
if poc: if ccx:
return get_override_for_poc(poc, block, name, default) return get_override_for_ccx(ccx, block, name, default)
return default return default
class _PocContext(threading.local): class _CcxContext(threading.local):
""" """
A threading local used to implement the `with_poc` context manager, that A threading local used to implement the `with_ccx` context manager, that
keeps track of the POC currently set as the context. keeps track of the CCX currently set as the context.
""" """
poc = None ccx = None
_POC_CONTEXT = _PocContext() _CCX_CONTEXT = _CcxContext()
@contextmanager @contextmanager
def poc_context(poc): def ccx_context(ccx):
""" """
A context manager which can be used to explicitly set the POC that is in A context manager which can be used to explicitly set the CCX that is in
play for field overrides. This mechanism overrides the standard mechanism play for field overrides. This mechanism overrides the standard mechanism
of looking in the user's session to see if they are enrolled in a POC and of looking in the user's session to see if they are enrolled in a CCX and
viewing that POC. viewing that CCX.
""" """
prev = _POC_CONTEXT.poc prev = _CCX_CONTEXT.ccx
_POC_CONTEXT.poc = poc _CCX_CONTEXT.ccx = ccx
yield yield
_POC_CONTEXT.poc = prev _CCX_CONTEXT.ccx = prev
def get_current_poc(): def get_current_ccx():
""" """
Return the poc that is active for this request. Return the ccx that is active for this request.
""" """
poc = _POC_CONTEXT.poc ccx = _CCX_CONTEXT.ccx
if poc: if ccx:
return poc return ccx
def get_override_for_poc(poc, block, name, default=None): def get_override_for_ccx(ccx, block, name, default=None):
""" """
Gets the value of the overridden field for the `poc`. `block` and `name` Gets the value of the overridden field for the `ccx`. `block` and `name`
specify the block and the name of the field. If the field is not specify the block and the name of the field. If the field is not
overridden for the given poc, returns `default`. overridden for the given ccx, returns `default`.
""" """
if not hasattr(block, '_poc_overrides'): if not hasattr(block, '_ccx_overrides'):
block._poc_overrides = {} block._ccx_overrides = {}
overrides = block._poc_overrides.get(poc.id) overrides = block._ccx_overrides.get(ccx.id)
if overrides is None: if overrides is None:
overrides = _get_overrides_for_poc(poc, block) overrides = _get_overrides_for_ccx(ccx, block)
block._poc_overrides[poc.id] = overrides block._ccx_overrides[ccx.id] = overrides
return overrides.get(name, default) return overrides.get(name, default)
def _get_overrides_for_poc(poc, block): def _get_overrides_for_ccx(ccx, block):
""" """
Returns a dictionary mapping field name to overriden value for any Returns a dictionary mapping field name to overriden value for any
overrides set on this block for this POC. overrides set on this block for this CCX.
""" """
overrides = {} overrides = {}
query = PocFieldOverride.objects.filter( query = CcxFieldOverride.objects.filter(
poc=poc, ccx=ccx,
location=block.location location=block.location
) )
for override in query: for override in query:
...@@ -92,68 +92,68 @@ def _get_overrides_for_poc(poc, block): ...@@ -92,68 +92,68 @@ def _get_overrides_for_poc(poc, block):
return overrides return overrides
def override_field_for_poc(poc, block, name, value): def override_field_for_ccx(ccx, block, name, value):
""" """
Overrides a field for the `poc`. `block` and `name` specify the block Overrides a field for the `ccx`. `block` and `name` specify the block
and the name of the field on that block to override. `value` is the and the name of the field on that block to override. `value` is the
value to set for the given field. value to set for the given field.
""" """
override, created = PocFieldOverride.objects.get_or_create( override, created = CcxFieldOverride.objects.get_or_create(
poc=poc, ccx=ccx,
location=block.location, location=block.location,
field=name) field=name)
field = block.fields[name] field = block.fields[name]
override.value = json.dumps(field.to_json(value)) override.value = json.dumps(field.to_json(value))
override.save() override.save()
if hasattr(block, '_poc_overrides'): if hasattr(block, '_ccx_overrides'):
del block._poc_overrides[poc.id] del block._ccx_overrides[ccx.id]
def clear_override_for_poc(poc, block, name): def clear_override_for_ccx(ccx, block, name):
""" """
Clears a previously set field override for the `poc`. `block` and `name` Clears a previously set field override for the `ccx`. `block` and `name`
specify the block and the name of the field on that block to clear. specify the block and the name of the field on that block to clear.
This function is idempotent--if no override is set, nothing action is This function is idempotent--if no override is set, nothing action is
performed. performed.
""" """
try: try:
PocFieldOverride.objects.get( CcxFieldOverride.objects.get(
poc=poc, ccx=ccx,
location=block.location, location=block.location,
field=name).delete() field=name).delete()
if hasattr(block, '_poc_overrides'): if hasattr(block, '_ccx_overrides'):
del block._poc_overrides[poc.id] del block._ccx_overrides[ccx.id]
except PocFieldOverride.DoesNotExist: except CcxFieldOverride.DoesNotExist:
pass pass
class PocMiddleware(object): class CcxMiddleware(object):
""" """
Checks to see if current session is examining a POC and sets the POC as Checks to see if current session is examining a CCX and sets the CCX as
the current POC for the override machinery if so. the current CCX for the override machinery if so.
""" """
def process_request(self, request): def process_request(self, request):
""" """
Do the check. Do the check.
""" """
poc_id = request.session.get(ACTIVE_POC_KEY, None) ccx_id = request.session.get(ACTIVE_CCX_KEY, None)
if poc_id is not None: if ccx_id is not None:
try: try:
membership = PocMembership.objects.get( membership = CcxMembership.objects.get(
student=request.user, active=True, poc__id__exact=poc_id student=request.user, active=True, ccx__id__exact=ccx_id
) )
_POC_CONTEXT.poc = membership.poc _CCX_CONTEXT.ccx = membership.ccx
except PocMembership.DoesNotExist: except CcxMembership.DoesNotExist:
# if there is no membership, be sure to unset the active poc # if there is no membership, be sure to unset the active ccx
_POC_CONTEXT.poc = None _CCX_CONTEXT.ccx = None
request.session.pop(ACTIVE_POC_KEY) request.session.pop(ACTIVE_CCX_KEY)
def process_response(self, request, response): def process_response(self, request, response):
""" """
Clean up afterwards. Clean up afterwards.
""" """
_POC_CONTEXT.poc = None _CCX_CONTEXT.ccx = None
return response return response
from factory.django import DjangoModelFactory
from ccx.models import CustomCourseForEdX
from ccx.models import CcxMembership
from ccx.models import CcxFutureMembership
class CcxFactory(DjangoModelFactory):
FACTORY_FOR = CustomCourseForEdX
display_name = "Test CCX"
class CcxMembershipFactory(DjangoModelFactory):
FACTORY_FOR = CcxMembership
active = False
class CcxFutureMembershipFactory(DjangoModelFactory):
FACTORY_FOR = CcxFutureMembership
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student.roles import CoursePocCoachRole from student.roles import CourseCcxCoachRole
from student.tests.factories import ( from student.tests.factories import (
AdminFactory, AdminFactory,
CourseEnrollmentFactory, CourseEnrollmentFactory,
...@@ -9,34 +9,35 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase ...@@ -9,34 +9,35 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from .factories import ( from .factories import (
PocFactory, CcxFactory,
PocMembershipFactory, CcxMembershipFactory,
PocFutureMembershipFactory, CcxFutureMembershipFactory,
) )
from ..models import ( from ..models import (
PocMembership, CcxMembership,
PocFutureMembership, CcxFutureMembership,
) )
class TestPocMembership(ModuleStoreTestCase): class TestCcxMembership(ModuleStoreTestCase):
"""Unit tests for the PocMembership model """Unit tests for the CcxMembership model
""" """
def setUp(self): def setUp(self):
"""common setup for all tests""" """common setup for all tests"""
super(TestCcxMembership, self).setUp()
self.course = course = CourseFactory.create() self.course = course = CourseFactory.create()
coach = AdminFactory.create() coach = AdminFactory.create()
role = CoursePocCoachRole(course.id) role = CourseCcxCoachRole(course.id)
role.add_users(coach) role.add_users(coach)
self.poc = PocFactory(course_id=course.id, coach=coach) self.ccx = CcxFactory(course_id=course.id, coach=coach)
enrollment = CourseEnrollmentFactory.create(course_id=course.id) enrollment = CourseEnrollmentFactory.create(course_id=course.id)
self.enrolled_user = enrollment.user self.enrolled_user = enrollment.user
self.unenrolled_user = UserFactory.create() self.unenrolled_user = UserFactory.create()
def create_future_enrollment(self, user, auto_enroll=True): def create_future_enrollment(self, user, auto_enroll=True):
pfm = PocFutureMembershipFactory.create( pfm = CcxFutureMembershipFactory.create(
poc=self.poc, ccx=self.ccx,
email=user.email, email=user.email,
auto_enroll=auto_enroll auto_enroll=auto_enroll
) )
...@@ -48,62 +49,62 @@ class TestPocMembership(ModuleStoreTestCase): ...@@ -48,62 +49,62 @@ class TestPocMembership(ModuleStoreTestCase):
) )
return enrollment.exists() return enrollment.exists()
def has_poc_membership(self, user): def has_ccx_membership(self, user):
membership = PocMembership.objects.filter( membership = CcxMembership.objects.filter(
student=user, poc=self.poc, active=True student=user, ccx=self.ccx, active=True
) )
return membership.exists() return membership.exists()
def has_poc_future_membership(self, user): def has_ccx_future_membership(self, user):
future_membership = PocFutureMembership.objects.filter( future_membership = CcxFutureMembership.objects.filter(
email=user.email, poc=self.poc email=user.email, ccx=self.ccx
) )
return future_membership.exists() return future_membership.exists()
def call_MUT(self, student, future_membership): def call_MUT(self, student, future_membership):
PocMembership.auto_enroll(student, future_membership) CcxMembership.auto_enroll(student, future_membership)
def test_poc_auto_enroll_unregistered_user(self): def test_ccx_auto_enroll_unregistered_user(self):
"""verify auto_enroll works when user is not enrolled in the MOOC """verify auto_enroll works when user is not enrolled in the MOOC
n.b. After auto_enroll, user will have both a MOOC enrollment and a n.b. After auto_enroll, user will have both a MOOC enrollment and a
POC membership CCX membership
""" """
user = self.unenrolled_user user = self.unenrolled_user
pfm = self.create_future_enrollment(user) pfm = self.create_future_enrollment(user)
self.assertTrue(self.has_poc_future_membership(user)) self.assertTrue(self.has_ccx_future_membership(user))
self.assertFalse(self.has_course_enrollment(user)) self.assertFalse(self.has_course_enrollment(user))
# auto_enroll user # auto_enroll user
self.call_MUT(user, pfm) self.call_MUT(user, pfm)
self.assertTrue(self.has_course_enrollment(user)) self.assertTrue(self.has_course_enrollment(user))
self.assertTrue(self.has_poc_membership(user)) self.assertTrue(self.has_ccx_membership(user))
self.assertFalse(self.has_poc_future_membership(user)) self.assertFalse(self.has_ccx_future_membership(user))
def test_poc_auto_enroll_registered_user(self): def test_ccx_auto_enroll_registered_user(self):
"""verify auto_enroll works when user is enrolled in the MOOC """verify auto_enroll works when user is enrolled in the MOOC
""" """
user = self.enrolled_user user = self.enrolled_user
pfm = self.create_future_enrollment(user) pfm = self.create_future_enrollment(user)
self.assertTrue(self.has_poc_future_membership(user)) self.assertTrue(self.has_ccx_future_membership(user))
self.assertTrue(self.has_course_enrollment(user)) self.assertTrue(self.has_course_enrollment(user))
self.call_MUT(user, pfm) self.call_MUT(user, pfm)
self.assertTrue(self.has_course_enrollment(user)) self.assertTrue(self.has_course_enrollment(user))
self.assertTrue(self.has_poc_membership(user)) self.assertTrue(self.has_ccx_membership(user))
self.assertFalse(self.has_poc_future_membership(user)) self.assertFalse(self.has_ccx_future_membership(user))
def test_future_membership_disallows_auto_enroll(self): def test_future_membership_disallows_auto_enroll(self):
"""verify that the PocFutureMembership can veto auto_enroll """verify that the CcxFutureMembership can veto auto_enroll
""" """
user = self.unenrolled_user user = self.unenrolled_user
pfm = self.create_future_enrollment(user, auto_enroll=False) pfm = self.create_future_enrollment(user, auto_enroll=False)
self.assertTrue(self.has_poc_future_membership(user)) self.assertTrue(self.has_ccx_future_membership(user))
self.assertFalse(self.has_course_enrollment(user)) self.assertFalse(self.has_course_enrollment(user))
self.assertRaises(ValueError, self.call_MUT, user, pfm) self.assertRaises(ValueError, self.call_MUT, user, pfm)
self.assertFalse(self.has_course_enrollment(user)) self.assertFalse(self.has_course_enrollment(user))
self.assertFalse(self.has_poc_membership(user)) self.assertFalse(self.has_ccx_membership(user))
self.assertTrue(self.has_poc_future_membership(user)) self.assertTrue(self.has_ccx_future_membership(user))
...@@ -8,12 +8,12 @@ from student.tests.factories import AdminFactory ...@@ -8,12 +8,12 @@ from student.tests.factories import AdminFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from ..models import PersonalOnlineCourse from ..models import CustomCourseForEdX
from ..overrides import override_field_for_poc from ..overrides import override_field_for_ccx
@override_settings(FIELD_OVERRIDE_PROVIDERS=( @override_settings(FIELD_OVERRIDE_PROVIDERS=(
'pocs.overrides.PersonalOnlineCoursesOverrideProvider',)) 'ccx.overrides.CustomCoursesForEdxOverrideProvider',))
class TestFieldOverrides(ModuleStoreTestCase): class TestFieldOverrides(ModuleStoreTestCase):
""" """
Make sure field overrides behave in the expected manner. Make sure field overrides behave in the expected manner.
...@@ -22,6 +22,7 @@ class TestFieldOverrides(ModuleStoreTestCase): ...@@ -22,6 +22,7 @@ class TestFieldOverrides(ModuleStoreTestCase):
""" """
Set up tests Set up tests
""" """
super(TestFieldOverrides, self).setUp()
self.course = course = CourseFactory.create() self.course = course = CourseFactory.create()
# Create a course outline # Create a course outline
...@@ -41,15 +42,15 @@ class TestFieldOverrides(ModuleStoreTestCase): ...@@ -41,15 +42,15 @@ class TestFieldOverrides(ModuleStoreTestCase):
[ItemFactory.create(parent=vertical) for _ in xrange(2)] [ItemFactory.create(parent=vertical) for _ in xrange(2)]
for vertical in verticals]) for vertical in verticals])
self.poc = poc = PersonalOnlineCourse( self.ccx = ccx = CustomCourseForEdX(
course_id=course.id, course_id=course.id,
display_name='Test POC', display_name='Test CCX',
coach=AdminFactory.create()) coach=AdminFactory.create())
poc.save() ccx.save()
patch = mock.patch('pocs.overrides.get_current_poc') patch = mock.patch('ccx.overrides.get_current_ccx')
self.get_poc = get_poc = patch.start() self.get_ccx = get_ccx = patch.start()
get_poc.return_value = poc get_ccx.return_value = ccx
self.addCleanup(patch.stop) self.addCleanup(patch.stop)
# Apparently the test harness doesn't use LmsFieldStorage, and I'm not # Apparently the test harness doesn't use LmsFieldStorage, and I'm not
...@@ -60,24 +61,30 @@ class TestFieldOverrides(ModuleStoreTestCase): ...@@ -60,24 +61,30 @@ class TestFieldOverrides(ModuleStoreTestCase):
block._field_data = OverrideFieldData.wrap( # pylint: disable=protected-access block._field_data = OverrideFieldData.wrap( # pylint: disable=protected-access
AdminFactory.create(), block._field_data) # pylint: disable=protected-access AdminFactory.create(), block._field_data) # pylint: disable=protected-access
# and after everything is done, clean up by un-doing the change to the
# OverrideFieldData object that is done during the wrap method.
def cleanup_provider_classes():
OverrideFieldData.provider_classes = None
self.addCleanup(cleanup_provider_classes)
def test_override_start(self): def test_override_start(self):
""" """
Test that overriding start date on a chapter works. Test that overriding start date on a chapter works.
""" """
poc_start = datetime.datetime(2014, 12, 25, 00, 00, tzinfo=pytz.UTC) ccx_start = datetime.datetime(2014, 12, 25, 00, 00, tzinfo=pytz.UTC)
chapter = self.course.get_children()[0] chapter = self.course.get_children()[0]
override_field_for_poc(self.poc, chapter, 'start', poc_start) override_field_for_ccx(self.ccx, chapter, 'start', ccx_start)
self.assertEquals(chapter.start, poc_start) self.assertEquals(chapter.start, ccx_start)
def test_override_is_inherited(self): def test_override_is_inherited(self):
""" """
Test that sequentials inherit overridden start date from chapter. Test that sequentials inherit overridden start date from chapter.
""" """
poc_start = datetime.datetime(2014, 12, 25, 00, 00, tzinfo=pytz.UTC) ccx_start = datetime.datetime(2014, 12, 25, 00, 00, tzinfo=pytz.UTC)
chapter = self.course.get_children()[0] chapter = self.course.get_children()[0]
override_field_for_poc(self.poc, chapter, 'start', poc_start) override_field_for_ccx(self.ccx, chapter, 'start', ccx_start)
self.assertEquals(chapter.get_children()[0].start, poc_start) self.assertEquals(chapter.get_children()[0].start, ccx_start)
self.assertEquals(chapter.get_children()[1].start, poc_start) self.assertEquals(chapter.get_children()[1].start, ccx_start)
def test_override_is_inherited_even_if_set_in_mooc(self): def test_override_is_inherited_even_if_set_in_mooc(self):
""" """
...@@ -85,12 +92,12 @@ class TestFieldOverrides(ModuleStoreTestCase): ...@@ -85,12 +92,12 @@ class TestFieldOverrides(ModuleStoreTestCase):
(verticals) even if a due date is set explicitly on grandchildren in (verticals) even if a due date is set explicitly on grandchildren in
the mooc. the mooc.
""" """
poc_due = datetime.datetime(2015, 1, 1, 00, 00, tzinfo=pytz.UTC) ccx_due = datetime.datetime(2015, 1, 1, 00, 00, tzinfo=pytz.UTC)
chapter = self.course.get_children()[0] chapter = self.course.get_children()[0]
chapter.display_name = 'itsme!' chapter.display_name = 'itsme!'
override_field_for_poc(self.poc, chapter, 'due', poc_due) override_field_for_ccx(self.ccx, chapter, 'due', ccx_due)
vertical = chapter.get_children()[0].get_children()[0] vertical = chapter.get_children()[0].get_children()[0]
self.assertEqual(vertical.due, poc_due) self.assertEqual(vertical.due, ccx_due)
def flatten(seq): def flatten(seq):
......
...@@ -248,7 +248,7 @@ def _grade(student, request, course, keep_raw_scores): ...@@ -248,7 +248,7 @@ def _grade(student, request, course, keep_raw_scores):
totaled_scores[section_format] = format_scores totaled_scores[section_format] = format_scores
# Grading policy might be overriden by a POC, need to reset it # Grading policy might be overriden by a CCX, need to reset it
course.set_grading_policy(course.grading_policy) course.set_grading_policy(course.grading_policy)
grade_summary = course.grader.grade(totaled_scores, generate_random_scores=settings.GENERATE_PROFILE_SCORES) grade_summary = course.grader.grade(totaled_scores, generate_random_scores=settings.GENERATE_PROFILE_SCORES)
......
...@@ -15,7 +15,7 @@ from django_comment_common.models import Role ...@@ -15,7 +15,7 @@ from django_comment_common.models import Role
from student.roles import ( from student.roles import (
CourseBetaTesterRole, CourseBetaTesterRole,
CourseInstructorRole, CourseInstructorRole,
CoursePocCoachRole, CourseCcxCoachRole,
CourseStaffRole, CourseStaffRole,
) )
...@@ -26,7 +26,7 @@ ROLES = { ...@@ -26,7 +26,7 @@ ROLES = {
'beta': CourseBetaTesterRole, 'beta': CourseBetaTesterRole,
'instructor': CourseInstructorRole, 'instructor': CourseInstructorRole,
'staff': CourseStaffRole, 'staff': CourseStaffRole,
'poc_coach': CoursePocCoachRole, 'ccx_coach': CourseCcxCoachRole,
} }
......
...@@ -679,7 +679,7 @@ def bulk_beta_modify_access(request, course_id): ...@@ -679,7 +679,7 @@ def bulk_beta_modify_access(request, course_id):
@common_exceptions_400 @common_exceptions_400
@require_query_params( @require_query_params(
unique_student_identifier="email or username of user to change access", unique_student_identifier="email or username of user to change access",
rolename="'instructor', 'staff', 'beta', or 'poc_coach'", rolename="'instructor', 'staff', 'beta', or 'ccx_coach'",
action="'allow' or 'revoke'" action="'allow' or 'revoke'"
) )
def modify_access(request, course_id): def modify_access(request, course_id):
...@@ -691,7 +691,7 @@ def modify_access(request, course_id): ...@@ -691,7 +691,7 @@ def modify_access(request, course_id):
Query parameters: Query parameters:
unique_student_identifer is the target user's username or email unique_student_identifer is the target user's username or email
rolename is one of ['instructor', 'staff', 'beta', 'poc_coach'] rolename is one of ['instructor', 'staff', 'beta', 'ccx_coach']
action is one of ['allow', 'revoke'] action is one of ['allow', 'revoke']
""" """
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id) course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
...@@ -762,7 +762,7 @@ def list_course_role_members(request, course_id): ...@@ -762,7 +762,7 @@ def list_course_role_members(request, course_id):
List instructors and staff. List instructors and staff.
Requires instructor access. Requires instructor access.
rolename is one of ['instructor', 'staff', 'beta', 'poc_coach'] rolename is one of ['instructor', 'staff', 'beta', 'ccx_coach']
Returns JSON of the form { Returns JSON of the form {
"course_id": "some/course/id", "course_id": "some/course/id",
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'PocFutureMembership'
db.create_table('pocs_pocfuturemembership', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('poc', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['pocs.PersonalOnlineCourse'])),
('email', self.gf('django.db.models.fields.CharField')(max_length=255)),
))
db.send_create_signal('pocs', ['PocFutureMembership'])
# Adding field 'PocMembership.active'
db.add_column('pocs_pocmembership', 'active',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
def backwards(self, orm):
# Deleting model 'PocFutureMembership'
db.delete_table('pocs_pocfuturemembership')
# Deleting field 'PocMembership.active'
db.delete_column('pocs_pocmembership', 'active')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'pocs.personalonlinecourse': {
'Meta': {'object_name': 'PersonalOnlineCourse'},
'coach': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'pocs.pocfieldoverride': {
'Meta': {'unique_together': "(('poc', 'location', 'field'),)", 'object_name': 'PocFieldOverride'},
'field': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location': ('xmodule_django.models.LocationKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"}),
'value': ('django.db.models.fields.TextField', [], {'default': "'null'"})
},
'pocs.pocfuturemembership': {
'Meta': {'object_name': 'PocFutureMembership'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"})
},
'pocs.pocmembership': {
'Meta': {'object_name': 'PocMembership'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"}),
'student': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}
complete_apps = ['pocs']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'PocFutureMembership.auto_enroll'
db.add_column('pocs_pocfuturemembership', 'auto_enroll',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
def backwards(self, orm):
# Deleting field 'PocFutureMembership.auto_enroll'
db.delete_column('pocs_pocfuturemembership', 'auto_enroll')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'pocs.personalonlinecourse': {
'Meta': {'object_name': 'PersonalOnlineCourse'},
'coach': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'pocs.pocfieldoverride': {
'Meta': {'unique_together': "(('poc', 'location', 'field'),)", 'object_name': 'PocFieldOverride'},
'field': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location': ('xmodule_django.models.LocationKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"}),
'value': ('django.db.models.fields.TextField', [], {'default': "'null'"})
},
'pocs.pocfuturemembership': {
'Meta': {'object_name': 'PocFutureMembership'},
'auto_enroll': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"})
},
'pocs.pocmembership': {
'Meta': {'object_name': 'PocMembership'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pocs.PersonalOnlineCourse']"}),
'student': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}
complete_apps = ['pocs']
\ No newline at end of file
from factory.django import DjangoModelFactory
from pocs.models import PersonalOnlineCourse
from pocs.models import PocMembership
from pocs.models import PocFutureMembership
class PocFactory(DjangoModelFactory):
FACTORY_FOR = PersonalOnlineCourse
display_name = "Test POC"
class PocMembershipFactory(DjangoModelFactory):
FACTORY_FOR = PocMembership
active = False
class PocFutureMembershipFactory(DjangoModelFactory):
FACTORY_FOR = PocFutureMembership
...@@ -577,12 +577,12 @@ ECOMMERCE_API_URL = ENV_TOKENS.get('ECOMMERCE_API_URL', ECOMMERCE_API_URL) ...@@ -577,12 +577,12 @@ ECOMMERCE_API_URL = ENV_TOKENS.get('ECOMMERCE_API_URL', ECOMMERCE_API_URL)
ECOMMERCE_API_SIGNING_KEY = AUTH_TOKENS.get('ECOMMERCE_API_SIGNING_KEY', ECOMMERCE_API_SIGNING_KEY) ECOMMERCE_API_SIGNING_KEY = AUTH_TOKENS.get('ECOMMERCE_API_SIGNING_KEY', ECOMMERCE_API_SIGNING_KEY)
ECOMMERCE_API_TIMEOUT = ENV_TOKENS.get('ECOMMERCE_API_TIMEOUT', ECOMMERCE_API_TIMEOUT) ECOMMERCE_API_TIMEOUT = ENV_TOKENS.get('ECOMMERCE_API_TIMEOUT', ECOMMERCE_API_TIMEOUT)
##### Personal Online Courses ##### ##### Custom Courses for EdX #####
if FEATURES.get('PERSONAL_ONLINE_COURSES'): if FEATURES.get('CUSTOM_COURSES_EDX'):
INSTALLED_APPS += ('pocs',) INSTALLED_APPS += ('ccx',)
MIDDLEWARE_CLASSES += ('pocs.overrides.PocMiddleware',) MIDDLEWARE_CLASSES += ('ccx.overrides.CcxMiddleware',)
FIELD_OVERRIDE_PROVIDERS += ( FIELD_OVERRIDE_PROVIDERS += (
'pocs.overrides.PersonalOnlineCoursesOverrideProvider', 'ccx.overrides.CustomCoursesForEdxOverrideProvider',
) )
##### Individual Due Date Extensions ##### ##### Individual Due Date Extensions #####
......
...@@ -214,8 +214,8 @@ FEATURES = { ...@@ -214,8 +214,8 @@ FEATURES = {
# True. # True.
'INDIVIDUAL_DUE_DATES': False, 'INDIVIDUAL_DUE_DATES': False,
# Enable Personal Online Courses # Enable Custom Courses for EdX
'PERSONAL_ONLINE_COURSES': False, 'CUSTOM_COURSES_EDX': False,
# Enable legacy instructor dashboard # Enable legacy instructor dashboard
'ENABLE_INSTRUCTOR_LEGACY_DASHBOARD': True, 'ENABLE_INSTRUCTOR_LEGACY_DASHBOARD': True,
...@@ -1203,7 +1203,8 @@ reverify_js = [ ...@@ -1203,7 +1203,8 @@ reverify_js = [
'js/verify_student/incourse_reverify.js', 'js/verify_student/incourse_reverify.js',
] ]
pocs_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/pocs/**/*.js')) ccx_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/ccx/**/*.js'))
PIPELINE_CSS = { PIPELINE_CSS = {
'style-vendor': { 'style-vendor': {
...@@ -1399,9 +1400,9 @@ PIPELINE_JS = { ...@@ -1399,9 +1400,9 @@ PIPELINE_JS = {
'source_filenames': reverify_js, 'source_filenames': reverify_js,
'output_filename': 'js/reverify.js' 'output_filename': 'js/reverify.js'
}, },
'pocs': { 'ccx': {
'source_filenames': pocs_js, 'source_filenames': ccx_js,
'output_filename': 'js/pocs.js' 'output_filename': 'js/ccx.js'
} }
} }
......
...@@ -469,6 +469,6 @@ FACEBOOK_API_VERSION = "v2.2" ...@@ -469,6 +469,6 @@ FACEBOOK_API_VERSION = "v2.2"
# Certificates Views # Certificates Views
FEATURES['CERTIFICATES_HTML_VIEW'] = True FEATURES['CERTIFICATES_HTML_VIEW'] = True
######### personal online courses ######### ######### custom courses #########
INSTALLED_APPS += ('pocs',) INSTALLED_APPS += ('ccx',)
MIDDLEWARE_CLASSES += ('pocs.overrides.PocMiddleware',) MIDDLEWARE_CLASSES += ('ccx.overrides.CcxMiddleware',)
...@@ -3,18 +3,18 @@ var edx = edx || {}; ...@@ -3,18 +3,18 @@ var edx = edx || {};
(function($, _, Backbone, gettext) { (function($, _, Backbone, gettext) {
'use strict'; 'use strict';
edx.pocs = edx.pocs || {}; edx.ccx = edx.ccx || {};
edx.pocs.schedule = edx.pocs.schedule || {}; edx.ccx.schedule = edx.ccx.schedule || {};
var syncErrorMessage = gettext("The data could not be saved."); var syncErrorMessage = gettext("The data could not be saved.");
var self; var self;
edx.pocs.schedule.reloadPage = function() { edx.ccx.schedule.reloadPage = function() {
location.reload(); location.reload();
}; };
edx.pocs.schedule.UnitModel = Backbone.Model.extend({ edx.ccx.schedule.UnitModel = Backbone.Model.extend({
defaults: { defaults: {
location: '', location: '',
display_name: '', display_name: '',
...@@ -27,18 +27,18 @@ var edx = edx || {}; ...@@ -27,18 +27,18 @@ var edx = edx || {};
}); });
edx.pocs.schedule.Schedule = Backbone.Collection.extend({ edx.ccx.schedule.Schedule = Backbone.Collection.extend({
model: edx.pocs.schedule.UnitModel, model: edx.ccx.schedule.UnitModel,
url: 'poc_schedule' url: 'ccx_schedule'
}); });
edx.pocs.schedule.ScheduleView = Backbone.View.extend({ edx.ccx.schedule.ScheduleView = Backbone.View.extend({
initialize: function() { initialize: function() {
_.bindAll(this, 'render'); _.bindAll(this, 'render');
this.schedule_collection = new edx.pocs.schedule.Schedule(); this.schedule_collection = new edx.ccx.schedule.Schedule();
this.schedule = {}; this.schedule = {};
this.schedule_collection.bind('reset', this.render); this.schedule_collection.bind('reset', this.render);
this.schedule_collection.fetch({reset: true}); this.schedule_collection.fetch({reset: true});
...@@ -63,23 +63,23 @@ var edx = edx || {}; ...@@ -63,23 +63,23 @@ var edx = edx || {};
this.showing = this.pruned(self.schedule, function(node) { this.showing = this.pruned(self.schedule, function(node) {
return !node.hidden}); return !node.hidden});
this.$el.html(schedule_template({chapters: this.showing})); this.$el.html(schedule_template({chapters: this.showing}));
$('table.poc-schedule .sequential,.vertical').hide(); $('table.ccx-schedule .sequential,.vertical').hide();
$('table.poc-schedule .toggle-collapse').on('click', this.toggle_collapse); $('table.ccx-schedule .toggle-collapse').on('click', this.toggle_collapse);
// //
// Hidden hover fields for empty date fields // Hidden hover fields for empty date fields
$('table.poc-schedule .date a').each(function() { $('table.ccx-schedule .date a').each(function() {
if (! $(this).text()) { if (! $(this).text()) {
$(this).text('Set date').addClass('empty'); $(this).text('Set date').addClass('empty');
} }
}); });
// Handle date edit clicks // Handle date edit clicks
$('table.poc-schedule .date a').attr('href', '#enter-date-modal') $('table.ccx-schedule .date a').attr('href', '#enter-date-modal')
.leanModal({closeButton: '.close-modal'}); .leanModal({closeButton: '.close-modal'});
$('table.poc-schedule .due-date a').on('click', this.enterNewDate('due')); $('table.ccx-schedule .due-date a').on('click', this.enterNewDate('due'));
$('table.poc-schedule .start-date a').on('click', this.enterNewDate('start')); $('table.ccx-schedule .start-date a').on('click', this.enterNewDate('start'));
// Click handler for remove all // Click handler for remove all
$('table.poc-schedule a#remove-all').on('click', function(event) { $('table.ccx-schedule a#remove-all').on('click', function(event) {
event.preventDefault(); event.preventDefault();
self.schedule_apply(self.schedule, self.hide); self.schedule_apply(self.schedule, self.hide);
self.dirty = true; self.dirty = true;
...@@ -175,7 +175,7 @@ var edx = edx || {}; ...@@ -175,7 +175,7 @@ var edx = edx || {};
}); });
// Remove unit handler // Remove unit handler
$('table.poc-schedule a.remove-unit').on('click', function(event) { $('table.ccx-schedule a.remove-unit').on('click', function(event) {
var row = $(this).closest('tr'), var row = $(this).closest('tr'),
path = row.data('location').split(' '), path = row.data('location').split(' '),
unit = self.find_unit(self.schedule, path[0], path[1], path[2]); unit = self.find_unit(self.schedule, path[0], path[1], path[2]);
......
...@@ -77,8 +77,8 @@ ...@@ -77,8 +77,8 @@
@import "course/instructor/email"; @import "course/instructor/email";
@import "xmodule/descriptors/css/module-styles.scss"; @import "xmodule/descriptors/css/module-styles.scss";
// course - poc_coach // course - ccx_coach
@import "course/poc_coach/dashboard"; @import "course/ccx_coach/dashboard";
// discussion // discussion
@import "course/discussion/form-wmd-toolbar"; @import "course/discussion/form-wmd-toolbar";
.poc-schedule-container { .ccx-schedule-container {
float: left; float: left;
width: 750px; width: 750px;
} }
table.poc-schedule { table.ccx-schedule {
width: 100%; width: 100%;
thead { thead {
...@@ -34,19 +34,19 @@ table.poc-schedule { ...@@ -34,19 +34,19 @@ table.poc-schedule {
} }
} }
.poc-schedule-sidebar { .ccx-schedule-sidebar {
float: left; float: left;
width: 295px; width: 295px;
margin-left: 20px; margin-left: 20px;
} }
.poc-sidebar-panel { .ccx-sidebar-panel {
border: 1px solid #cbcbcb; border: 1px solid #cbcbcb;
padding: 15px; padding: 15px;
margin-bottom: 20px; margin-bottom: 20px;
} }
form.poc-form { form.ccx-form {
line-height: 1.5; line-height: 1.5;
select { select {
width: 100%; width: 100%;
......
<%page args="poc, membership, course" /> <%page args="ccx, membership, course" />
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! <%!
...@@ -6,24 +6,24 @@ ...@@ -6,24 +6,24 @@
from courseware.courses import course_image_url, get_course_about_section from courseware.courses import course_image_url, get_course_about_section
%> %>
<% <%
poc_switch_target = reverse('switch_active_poc', args=[course.id.to_deprecated_string(), poc.id]) ccx_switch_target = reverse('switch_active_ccx', args=[course.id.to_deprecated_string(), ccx.id])
%> %>
<li class="course-item"> <li class="course-item">
<article class="course"> <article class="course">
<a href="${poc_switch_target}" class="cover"> <a href="${ccx_switch_target}" class="cover">
<img src="${course_image_url(course)}" alt="${_('{course_number} {poc_name} Cover Image').format(course_number=course.number, poc_name=poc.display_name) |h}" /> <img src="${course_image_url(course)}" alt="${_('{course_number} {ccx_name} Cover Image').format(course_number=course.number, ccx_name=ccx.display_name) |h}" />
</a> </a>
<section class="info"> <section class="info">
<hgroup> <hgroup>
<p class="date-block"> <p class="date-block">
Personal Online Course Custom Course
</p> </p>
<h2 class="university">${get_course_about_section(course, 'university')}</h2> <h2 class="university">${get_course_about_section(course, 'university')}</h2>
<h3> <h3>
<a href="${poc_switch_target}">${course.display_number_with_default | h} ${poc.display_name}</a> <a href="${ccx_switch_target}">${course.display_number_with_default | h} ${ccx.display_name}</a>
</h3> </h3>
</hgroup> </hgroup>
<a href="${poc_switch_target}" class="enter-course">${_('View Course')}</a> <a href="${ccx_switch_target}" class="enter-course">${_('View Course')}</a>
</section> </section>
</article> </article>
</li> </li>
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
<%inherit file="/main.html" /> <%inherit file="/main.html" />
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
<%block name="pagetitle">${_("POC Coach Dashboard")}</%block> <%block name="pagetitle">${_("CCX Coach Dashboard")}</%block>
<%block name="nav_skip">#poc-coach-dashboard-content</%block> <%block name="nav_skip">#ccx-coach-dashboard-content</%block>
<%block name="headextra"> <%block name="headextra">
<%static:css group='style-course-vendor'/> <%static:css group='style-course-vendor'/>
...@@ -14,24 +14,24 @@ ...@@ -14,24 +14,24 @@
<%static:css group='style-course'/> <%static:css group='style-course'/>
</%block> </%block>
<%include file="/courseware/course_navigation.html" args="active_page='poc_coach'" /> <%include file="/courseware/course_navigation.html" args="active_page='ccx_coach'" />
<section class="container"> <section class="container">
<div class="instructor-dashboard-wrapper-2"> <div class="instructor-dashboard-wrapper-2">
<section class="instructor-dashboard-content-2" id="poc-coach-dashboard-content"> <section class="instructor-dashboard-content-2" id="ccx-coach-dashboard-content">
<h1>${_("POC Coach Dashboard")}</h1> <h1>${_("CCX Coach Dashboard")}</h1>
%if not poc: %if not ccx:
<section> <section>
<form action="${create_poc_url}" method="POST"> <form action="${create_ccx_url}" method="POST">
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"/> <input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"/>
<input name="name" placeholder="Name your POC"/><br/> <input name="name" placeholder="Name your CCX"/><br/>
<button id="create-poc">Coach a new Personal Online Course</button> <button id="create-ccx">Coach a new Custom Course for EdX</button>
</form> </form>
</section> </section>
%endif %endif
%if poc: %if ccx:
<ul class="instructor-nav"> <ul class="instructor-nav">
<li class="nav-item"> <li class="nav-item">
<a href="#" data-section="membership">${_("Enrollment")}</a> <a href="#" data-section="membership">${_("Enrollment")}</a>
......
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<div class="batch-enrollment" style="float:left;width:50%"> <div class="batch-enrollment" style="float:left;width:50%">
<form method="POST" action="poc_invite"> <form method="POST" action="ccx_invite">
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }"> <input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
<h2> ${_("Batch Enrollment")} </h2> <h2> ${_("Batch Enrollment")} </h2>
<p> <p>
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
</div> </div>
<div class="member-lists-management" style="float:left;width:50%"> <div class="member-lists-management" style="float:left;width:50%">
<form method="POST" action="poc_manage_student"> <form method="POST" action="ccx_manage_student">
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }"> <input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
<div class="auth-list-container active"> <div class="auth-list-container active">
<div class="member-list-widget"> <div class="member-list-widget">
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
%for member in poc_members: %for member in ccx_members:
<tr> <tr>
<td>${member.student}</td> <td>${member.student}</td>
<td>${member.student.email}</td> <td>${member.student.email}</td>
......
...@@ -15,18 +15,18 @@ ...@@ -15,18 +15,18 @@
.ui-datepicker { z-index: 100000 !important; } .ui-datepicker { z-index: 100000 !important; }
input.date, input.time { width: auto !important; display: inline !important; } input.date, input.time { width: auto !important; display: inline !important; }
</style> </style>
<%static:js group='pocs'/> <%static:js group='ccx'/>
</%block> </%block>
%for template_name in ["schedule"]: %for template_name in ["schedule"]:
<script type="text/template" id="poc-${template_name}-template"> <script type="text/template" id="ccx-${template_name}-template">
<%static:include path="pocs/${template_name}.underscore" /> <%static:include path="ccx/${template_name}.underscore" />
</script> </script>
%endfor %endfor
<div class="poc-schedule-container"> <div class="ccx-schedule-container">
<div id="poc-schedule"></div> <div id="ccx-schedule"></div>
<div id="new-poc-schedule"></div> <div id="new-ccx-schedule"></div>
</div> </div>
<section id="enter-date-modal" class="modal" aria-hidden="true"> <section id="enter-date-modal" class="modal" aria-hidden="true">
...@@ -53,8 +53,8 @@ ...@@ -53,8 +53,8 @@
</div> </div>
</section> </section>
<div class="poc-schedule-sidebar"> <div class="ccx-schedule-sidebar">
<div class="poc-sidebar-panel" id="dirty-schedule"> <div class="ccx-sidebar-panel" id="dirty-schedule">
<h2>${_('Save changes')}</h2> <h2>${_('Save changes')}</h2>
<form role="form"> <form role="form">
<p>${_("You have unsaved changes.")}</p> <p>${_("You have unsaved changes.")}</p>
...@@ -64,13 +64,13 @@ ...@@ -64,13 +64,13 @@
</div> </div>
</form> </form>
</div> </div>
<div class="poc-sidebar-panel" id="ajax-error"> <div class="ccx-sidebar-panel" id="ajax-error">
<h2>${_('Error')}</h2> <h2>${_('Error')}</h2>
<p>${_("There was an error saving changes.")}</p> <p>${_("There was an error saving changes.")}</p>
</div> </div>
<div class="poc-sidebar-panel"> <div class="ccx-sidebar-panel">
<h2>${_('Schedule a Unit')}</h2> <h2>${_('Schedule a Unit')}</h2>
<form role="form" id="add-unit" name="add-unit" class="poc-form"> <form role="form" id="add-unit" name="add-unit" class="ccx-form">
<div class="field"> <div class="field">
<b>${_('Section')}</b><br/> <b>${_('Section')}</b><br/>
<select name="chapter"></select> <select name="chapter"></select>
...@@ -110,12 +110,12 @@ ...@@ -110,12 +110,12 @@
<script> <script>
$(function() { $(function() {
schedule_template = _.template($('#poc-schedule-template').html()); schedule_template = _.template($('#ccx-schedule-template').html());
var view = new edx.pocs.schedule.ScheduleView({ var view = new edx.ccx.schedule.ScheduleView({
el: $('#new-poc-schedule') el: $('#new-ccx-schedule')
}); });
view.render(); view.render();
//poc_schedule.render(); //ccx_schedule.render();
$('.datepair .time').timepicker({ $('.datepair .time').timepicker({
'showDuration': true, 'showDuration': true,
'timeFormat': 'G:i' 'timeFormat': 'G:i'
......
<table class="poc-schedule"> <table class="ccx-schedule">
<thead> <thead>
<tr> <tr>
<th><%- gettext('Unit') %></th> <th><%- gettext('Unit') %></th>
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<% _.each(chapters, function(chapter) { %> <% _.each(chapters, function(chapter) { %>
<tr class="chapter collapsed" data-location="<%= chapter.location %>" data-depth="1"> <tr class="chapter collapsed" data-location="<%= chapter.location %>" data-depth="1">
<td class="unit"> <td class="unit">
<a href="#"><i class="icon-caret-right icon toggle-collapse"></i></a> <a href="#"><i class="icon-caret-right icon toggle-collapse"></i></a>
<%= chapter.display_name %> <%= chapter.display_name %>
</td> </td>
<td class="date start-date"><a><%= chapter.start %></a></td> <td class="date start-date"><a><%= chapter.start %></a></td>
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
</a></td> </a></td>
</tr> </tr>
<% _.each(chapter.children, function(child) { %> <% _.each(chapter.children, function(child) { %>
<tr class="sequential collapsed" data-depth="2" <tr class="sequential collapsed" data-depth="2"
data-location="<%= chapter.location %> <%= child.location %>"> data-location="<%= chapter.location %> <%= child.location %>">
<td class="unit"> <td class="unit">
<a href="#"><i class="icon-caret-right icon toggle-collapse"></i></a> <a href="#"><i class="icon-caret-right icon toggle-collapse"></i></a>
<%= child.display_name %> <%= child.display_name %>
</td> </td>
<td class="date start-date"><a><%= child.start %></a></td> <td class="date start-date"><a><%= child.start %></a></td>
......
...@@ -243,9 +243,9 @@ ...@@ -243,9 +243,9 @@
<%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course, is_course_blocked = is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements" /> <%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course, is_course_blocked = is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements" />
% endfor % endfor
% if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False): % if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
% for poc, membership, course in poc_membership_triplets: % for ccx, membership, course in ccx_membership_triplets:
<%include file='pocs/_dashboard_poc_listing.html' args="poc=poc, membership=membership, course=course" /> <%include file='ccx/_dashboard_ccx_listing.html' args="ccx=ccx, membership=membership, course=course" />
% endfor % endfor
% endif % endif
......
...@@ -244,17 +244,17 @@ ...@@ -244,17 +244,17 @@
></div> ></div>
%endif %endif
%if section_data['access']['instructor'] and settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False): %if section_data['access']['instructor'] and settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
<div class="auth-list-container" <div class="auth-list-container"
data-rolename="poc_coach" data-rolename="ccx_coach"
data-display-name="${_("POC Coaches")}" data-display-name="${_("CCX Coaches")}"
data-info-text=" data-info-text="
${_("POC Coaches are able to create their own Personal Online Courses " ${_("CCX Coaches are able to create their own Custom Courses "
"based on this course, which they can use to provide personalized " "based on this course, which they can use to provide personalized "
"instruction to their own students based in this course material.")}" "instruction to their own students based in this course material.")}"
data-list-endpoint="${section_data['list_course_role_members_url']}" data-list-endpoint="${section_data['list_course_role_members_url']}"
data-modify-endpoint="${section_data['modify_access_url']}" data-modify-endpoint="${section_data['modify_access_url']}"
data-add-button-label="${_("Add POC Coach")}" data-add-button-label="${_("Add CCX Coach")}"
></div> ></div>
%endif %endif
</div> </div>
...@@ -13,7 +13,7 @@ from status.status import get_site_status_msg ...@@ -13,7 +13,7 @@ from status.status import get_site_status_msg
<%! from microsite_configuration import microsite %> <%! from microsite_configuration import microsite %>
<%! from microsite_configuration.templatetags.microsite import platform_name %> <%! from microsite_configuration.templatetags.microsite import platform_name %>
<%! from pocs.overrides import get_current_poc %> <%! from ccx.overrides import get_current_ccx %>
## Provide a hook for themes to inject branding on top. ## Provide a hook for themes to inject branding on top.
<%block name="navigation_top" /> <%block name="navigation_top" />
...@@ -52,10 +52,10 @@ site_status_msg = get_site_status_msg(course_id) ...@@ -52,10 +52,10 @@ site_status_msg = get_site_status_msg(course_id)
${course.display_number_with_default | h} ${course.display_number_with_default | h}
<% <%
display_name = course.display_name_with_default display_name = course.display_name_with_default
if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False): if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
poc = get_current_poc() ccx = get_current_ccx()
if poc: if ccx:
display_name = poc.display_name display_name = ccx.display_name
%> %>
${display_name}</h2> ${display_name}</h2>
% endif % endif
......
...@@ -343,26 +343,26 @@ if settings.COURSEWARE_ENABLED: ...@@ -343,26 +343,26 @@ if settings.COURSEWARE_ENABLED:
# For the instructor # For the instructor
url(r'^courses/{}/instructor$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/instructor$'.format(settings.COURSE_ID_PATTERN),
'instructor.views.instructor_dashboard.instructor_dashboard_2', name="instructor_dashboard"), 'instructor.views.instructor_dashboard.instructor_dashboard_2', name="instructor_dashboard"),
url(r'^courses/{}/poc_coach$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_coach$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.dashboard', name='poc_coach_dashboard'), 'ccx.views.dashboard', name='ccx_coach_dashboard'),
url(r'^courses/{}/create_poc$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/create_ccx$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.create_poc', name='create_poc'), 'ccx.views.create_ccx', name='create_ccx'),
url(r'^courses/{}/save_poc$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/save_ccx$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.save_poc', name='save_poc'), 'ccx.views.save_ccx', name='save_ccx'),
url(r'^courses/{}/poc_invite$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_invite$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.poc_invite', name='poc_invite'), 'ccx.views.ccx_invite', name='ccx_invite'),
url(r'^courses/{}/poc_schedule$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_schedule$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.poc_schedule', name='poc_schedule'), 'ccx.views.ccx_schedule', name='ccx_schedule'),
url(r'^courses/{}/poc_manage_student$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_manage_student$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.poc_student_management', name='poc_manage_student'), 'ccx.views.ccx_student_management', name='ccx_manage_student'),
url(r'^courses/{}/poc_gradebook$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_gradebook$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.poc_gradebook', name='poc_gradebook'), 'ccx.views.ccx_gradebook', name='ccx_gradebook'),
url(r'^courses/{}/poc_grades.csv$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_grades.csv$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.poc_grades_csv', name='poc_grades_csv'), 'ccx.views.ccx_grades_csv', name='ccx_grades_csv'),
url(r'^courses/{}/poc_set_grading_policy$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/ccx_set_grading_policy$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.set_grading_policy', name='poc_set_grading_policy'), 'ccx.views.set_grading_policy', name='ccx_set_grading_policy'),
url(r'^courses/{}/swich_poc(?:/(?P<poc_id>[\d]+))?$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/switch_ccx(?:/(?P<ccx_id>[\d]+))?$'.format(settings.COURSE_ID_PATTERN),
'pocs.views.swich_active_poc', name='switch_active_poc'), 'ccx.views.switch_active_ccx', name='switch_active_ccx'),
url(r'^courses/{}/set_course_mode_price$'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/set_course_mode_price$'.format(settings.COURSE_ID_PATTERN),
'instructor.views.instructor_dashboard.set_course_mode_price', name="set_course_mode_price"), 'instructor.views.instructor_dashboard.set_course_mode_price', name="set_course_mode_price"),
url(r'^courses/{}/instructor/api/'.format(settings.COURSE_ID_PATTERN), url(r'^courses/{}/instructor/api/'.format(settings.COURSE_ID_PATTERN),
......
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