From 470e40272345c330cd11ae9049a84804659a1986 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 15 Mar 2013 10:51:34 -0400 Subject: [PATCH 1/6] patch for backward compatibility --- lms/djangoapps/django_comment_client/base/views.py | 3 +++ lms/djangoapps/django_comment_client/forum/views.py | 10 ++++++++++ lms/templates/discussion/_underscore_templates.html | 12 +++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index 6734625a76..c021458ae3 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -116,6 +116,9 @@ def create_thread(request, course_id, commentable_id): thread.save() + #patch for backward compatibility with comments service + thread['pinned'] = False + if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(thread) diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index 50224e7de6..bb59a5675a 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -98,6 +98,9 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG else: thread['group_name'] = "" thread['group_string'] = "This post visible to everyone." + + #temporary patch for backward compatibility to comments service + thread['pinning'] = False query_params['page'] = page query_params['num_pages'] = num_pages @@ -245,6 +248,10 @@ def single_thread(request, course_id, discussion_id, thread_id): try: thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id) + + #temporary patch for backward compatibility with comments service + thread["pinned"] = False + except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError) as err: log.error("Error loading single thread.") raise Http404 @@ -285,6 +292,9 @@ def single_thread(request, course_id, discussion_id, thread_id): if thread.get('group_id') and not thread.get('group_name'): thread['group_name'] = get_cohort_by_id(course_id, thread.get('group_id')).name + #temporary patch for backward compatibility with comments service + thread["pinned"] = False + threads = [utils.safe_content(thread) for thread in threads] #recent_active_threads = cc.search_recent_active_threads( diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html index 5fdfb8aa82..21a881908f 100644 --- a/lms/templates/discussion/_underscore_templates.html +++ b/lms/templates/discussion/_underscore_templates.html @@ -45,11 +45,17 @@
${'<%- body %>'}
- - % if course and has_permission(user, 'openclose_thread', course.id): + + % if course and has_permission(user, 'openclose_thread', course.id) and False:
Pin Thread
- %else: + + + %elif False: ${"<% if (pinned) { %>"}
Pin Thread
From 0a53ec3ee6edb4f499a0a9073e9117bf13152123 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 15 Mar 2013 11:37:58 -0400 Subject: [PATCH 2/6] updates --- lms/templates/discussion/_underscore_templates.html | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html index 21a881908f..24e3b467be 100644 --- a/lms/templates/discussion/_underscore_templates.html +++ b/lms/templates/discussion/_underscore_templates.html @@ -45,17 +45,11 @@
${'<%- body %>'}
- - % if course and has_permission(user, 'openclose_thread', course.id) and False: + % if course and has_permission(user, 'openclose_thread', course.id):
Pin Thread
- - %elif False: + %else: ${"<% if (pinned) { %>"}
Pin Thread
@@ -63,9 +57,6 @@ % endif - - - ${'<% if (obj.courseware_url) { %>'}
(this post is about ${'<%- courseware_title %>'}) From a761e2e8297518ed03eab69b85a5f17735988701 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 15 Mar 2013 12:38:28 -0400 Subject: [PATCH 3/6] make pinning backward compatible --- .../views/discussion_thread_show_view.coffee | 4 +- .../django_comment_client/base/views.py | 5 +- .../django_comment_client/forum/views.py | 16 ++- lms/lib/comment_client/models.py | 131 ------------------ 4 files changed, 16 insertions(+), 140 deletions(-) delete mode 100644 lms/lib/comment_client/models.py diff --git a/common/static/coffee/src/discussion/views/discussion_thread_show_view.coffee b/common/static/coffee/src/discussion/views/discussion_thread_show_view.coffee index a5a1deac10..56525af347 100644 --- a/common/static/coffee/src/discussion/views/discussion_thread_show_view.coffee +++ b/common/static/coffee/src/discussion/views/discussion_thread_show_view.coffee @@ -128,7 +128,9 @@ if Backbone? type: "POST" success: (response, textStatus) => if textStatus == 'success' - @model.set('pinned', true) + @model.set('pinned', true) + error: => + $('.admin-pin').text("Pinning not currently available") unPin: -> url = @model.urlFor("unPinThread") diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index c021458ae3..6cb45ee64d 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -116,8 +116,9 @@ def create_thread(request, course_id, commentable_id): thread.save() - #patch for backward compatibility with comments service - thread['pinned'] = False + #patch for backward compatibility to comments service + if not 'pinned' in thread.attributes: + thread['pinned'] = False if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index bb59a5675a..445a9b139e 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -99,8 +99,10 @@ def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAG thread['group_name'] = "" thread['group_string'] = "This post visible to everyone." - #temporary patch for backward compatibility to comments service - thread['pinning'] = False + #patch for backward compatibility to comments service + if not 'pinned' in thread: + thread['pinned'] = False + query_params['page'] = page query_params['num_pages'] = num_pages @@ -249,8 +251,9 @@ def single_thread(request, course_id, discussion_id, thread_id): try: thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id) - #temporary patch for backward compatibility with comments service - thread["pinned"] = False + #patch for backward compatibility with comments service + if not 'pinned' in thread.attributes: + thread['pinned'] = False except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError) as err: log.error("Error loading single thread.") @@ -292,8 +295,9 @@ def single_thread(request, course_id, discussion_id, thread_id): if thread.get('group_id') and not thread.get('group_name'): thread['group_name'] = get_cohort_by_id(course_id, thread.get('group_id')).name - #temporary patch for backward compatibility with comments service - thread["pinned"] = False + #patch for backward compatibility with comments service + if not "pinned" in thread: + thread["pinned"] = False threads = [utils.safe_content(thread) for thread in threads] diff --git a/lms/lib/comment_client/models.py b/lms/lib/comment_client/models.py deleted file mode 100644 index 2a8992554d..0000000000 --- a/lms/lib/comment_client/models.py +++ /dev/null @@ -1,131 +0,0 @@ -from utils import * - - -class Model(object): - - accessible_fields = ['id'] - updatable_fields = ['id'] - initializable_fields = ['id'] - base_url = None - default_retrieve_params = {} - - DEFAULT_ACTIONS_WITH_ID = ['get', 'put', 'delete'] - DEFAULT_ACTIONS_WITHOUT_ID = ['get_all', 'post'] - DEFAULT_ACTIONS = DEFAULT_ACTIONS_WITH_ID + DEFAULT_ACTIONS_WITHOUT_ID - - def __init__(self, *args, **kwargs): - self.attributes = extract(kwargs, self.accessible_fields) - self.retrieved = False - - def __getattr__(self, name): - if name == 'id': - return self.attributes.get('id', None) - try: - return self.attributes[name] - except KeyError: - if self.retrieved or self.id is None: - raise AttributeError("Field {0} does not exist".format(name)) - self.retrieve() - return self.__getattr__(name) - - def __setattr__(self, name, value): - if name == 'attributes' or name not in self.accessible_fields: - super(Model, self).__setattr__(name, value) - else: - self.attributes[name] = value - - def __getitem__(self, key): - if key not in self.accessible_fields: - raise KeyError("Field {0} does not exist".format(key)) - return self.attributes.get(key) - - def __setitem__(self, key, value): - if key not in self.accessible_fields: - raise KeyError("Field {0} does not exist".format(key)) - self.attributes.__setitem__(key, value) - - def items(self, *args, **kwargs): - return self.attributes.items(*args, **kwargs) - - def get(self, *args, **kwargs): - return self.attributes.get(*args, **kwargs) - - def to_dict(self): - self.retrieve() - return self.attributes - - def retrieve(self, *args, **kwargs): - if not self.retrieved: - self._retrieve(*args, **kwargs) - self.retrieved = True - return self - - def _retrieve(self, *args, **kwargs): - url = self.url(action='get', params=self.attributes) - response = perform_request('get', url, self.default_retrieve_params) - self.update_attributes(**response) - - @classmethod - def find(cls, id): - return cls(id=id) - - def update_attributes(self, *args, **kwargs): - for k, v in kwargs.items(): - if k in self.accessible_fields: - self.__setattr__(k, v) - else: - raise AttributeError("Field {0} does not exist".format(k)) - - def updatable_attributes(self): - return extract(self.attributes, self.updatable_fields) - - def initializable_attributes(self): - return extract(self.attributes, self.initializable_fields) - - @classmethod - def before_save(cls, instance): - pass - - @classmethod - def after_save(cls, instance): - pass - - def save(self): - self.__class__.before_save(self) - if self.id: # if we have id already, treat this as an update - url = self.url(action='put', params=self.attributes) - response = perform_request('put', url, self.updatable_attributes()) - else: # otherwise, treat this as an insert - url = self.url(action='post', params=self.attributes) - response = perform_request('post', url, self.initializable_attributes()) - self.retrieved = True - self.update_attributes(**response) - self.__class__.after_save(self) - - def delete(self): - url = self.url(action='delete', params=self.attributes) - response = perform_request('delete', url) - self.retrieved = True - self.update_attributes(**response) - - @classmethod - def url_with_id(cls, params={}): - return cls.base_url + '/' + str(params['id']) - - @classmethod - def url_without_id(cls, params={}): - return cls.base_url - - @classmethod - def url(cls, action, params={}): - if cls.base_url is None: - raise CommentClientError("Must provide base_url when using default url function") - if action not in cls.DEFAULT_ACTIONS: - raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) - elif action in cls.DEFAULT_ACTIONS_WITH_ID: - try: - return cls.url_with_id(params) - except KeyError: - raise CommentClientError("Cannot perform action {0} without id".format(action)) - else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now - return cls.url_without_id() From 68cb63daa81212676bf87469d8e36eed090b8036 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 15 Mar 2013 12:42:59 -0400 Subject: [PATCH 4/6] accidentally deleted models file --- common/models.py | 131 +++++++++++++++++++++++++++++++ lms/lib/comment_client/models.py | 131 +++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 common/models.py create mode 100644 lms/lib/comment_client/models.py diff --git a/common/models.py b/common/models.py new file mode 100644 index 0000000000..2a8992554d --- /dev/null +++ b/common/models.py @@ -0,0 +1,131 @@ +from utils import * + + +class Model(object): + + accessible_fields = ['id'] + updatable_fields = ['id'] + initializable_fields = ['id'] + base_url = None + default_retrieve_params = {} + + DEFAULT_ACTIONS_WITH_ID = ['get', 'put', 'delete'] + DEFAULT_ACTIONS_WITHOUT_ID = ['get_all', 'post'] + DEFAULT_ACTIONS = DEFAULT_ACTIONS_WITH_ID + DEFAULT_ACTIONS_WITHOUT_ID + + def __init__(self, *args, **kwargs): + self.attributes = extract(kwargs, self.accessible_fields) + self.retrieved = False + + def __getattr__(self, name): + if name == 'id': + return self.attributes.get('id', None) + try: + return self.attributes[name] + except KeyError: + if self.retrieved or self.id is None: + raise AttributeError("Field {0} does not exist".format(name)) + self.retrieve() + return self.__getattr__(name) + + def __setattr__(self, name, value): + if name == 'attributes' or name not in self.accessible_fields: + super(Model, self).__setattr__(name, value) + else: + self.attributes[name] = value + + def __getitem__(self, key): + if key not in self.accessible_fields: + raise KeyError("Field {0} does not exist".format(key)) + return self.attributes.get(key) + + def __setitem__(self, key, value): + if key not in self.accessible_fields: + raise KeyError("Field {0} does not exist".format(key)) + self.attributes.__setitem__(key, value) + + def items(self, *args, **kwargs): + return self.attributes.items(*args, **kwargs) + + def get(self, *args, **kwargs): + return self.attributes.get(*args, **kwargs) + + def to_dict(self): + self.retrieve() + return self.attributes + + def retrieve(self, *args, **kwargs): + if not self.retrieved: + self._retrieve(*args, **kwargs) + self.retrieved = True + return self + + def _retrieve(self, *args, **kwargs): + url = self.url(action='get', params=self.attributes) + response = perform_request('get', url, self.default_retrieve_params) + self.update_attributes(**response) + + @classmethod + def find(cls, id): + return cls(id=id) + + def update_attributes(self, *args, **kwargs): + for k, v in kwargs.items(): + if k in self.accessible_fields: + self.__setattr__(k, v) + else: + raise AttributeError("Field {0} does not exist".format(k)) + + def updatable_attributes(self): + return extract(self.attributes, self.updatable_fields) + + def initializable_attributes(self): + return extract(self.attributes, self.initializable_fields) + + @classmethod + def before_save(cls, instance): + pass + + @classmethod + def after_save(cls, instance): + pass + + def save(self): + self.__class__.before_save(self) + if self.id: # if we have id already, treat this as an update + url = self.url(action='put', params=self.attributes) + response = perform_request('put', url, self.updatable_attributes()) + else: # otherwise, treat this as an insert + url = self.url(action='post', params=self.attributes) + response = perform_request('post', url, self.initializable_attributes()) + self.retrieved = True + self.update_attributes(**response) + self.__class__.after_save(self) + + def delete(self): + url = self.url(action='delete', params=self.attributes) + response = perform_request('delete', url) + self.retrieved = True + self.update_attributes(**response) + + @classmethod + def url_with_id(cls, params={}): + return cls.base_url + '/' + str(params['id']) + + @classmethod + def url_without_id(cls, params={}): + return cls.base_url + + @classmethod + def url(cls, action, params={}): + if cls.base_url is None: + raise CommentClientError("Must provide base_url when using default url function") + if action not in cls.DEFAULT_ACTIONS: + raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) + elif action in cls.DEFAULT_ACTIONS_WITH_ID: + try: + return cls.url_with_id(params) + except KeyError: + raise CommentClientError("Cannot perform action {0} without id".format(action)) + else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now + return cls.url_without_id() diff --git a/lms/lib/comment_client/models.py b/lms/lib/comment_client/models.py new file mode 100644 index 0000000000..bf5f576a44 --- /dev/null +++ b/lms/lib/comment_client/models.py @@ -0,0 +1,131 @@ +from .utils import * + + +class Model(object): + + accessible_fields = ['id'] + updatable_fields = ['id'] + initializable_fields = ['id'] + base_url = None + default_retrieve_params = {} + + DEFAULT_ACTIONS_WITH_ID = ['get', 'put', 'delete'] + DEFAULT_ACTIONS_WITHOUT_ID = ['get_all', 'post'] + DEFAULT_ACTIONS = DEFAULT_ACTIONS_WITH_ID + DEFAULT_ACTIONS_WITHOUT_ID + + def __init__(self, *args, **kwargs): + self.attributes = extract(kwargs, self.accessible_fields) + self.retrieved = False + + def __getattr__(self, name): + if name == 'id': + return self.attributes.get('id', None) + try: + return self.attributes[name] + except KeyError: + if self.retrieved or self.id is None: + raise AttributeError("Field {0} does not exist".format(name)) + self.retrieve() + return self.__getattr__(name) + + def __setattr__(self, name, value): + if name == 'attributes' or name not in self.accessible_fields: + super(Model, self).__setattr__(name, value) + else: + self.attributes[name] = value + + def __getitem__(self, key): + if key not in self.accessible_fields: + raise KeyError("Field {0} does not exist".format(key)) + return self.attributes.get(key) + + def __setitem__(self, key, value): + if key not in self.accessible_fields: + raise KeyError("Field {0} does not exist".format(key)) + self.attributes.__setitem__(key, value) + + def items(self, *args, **kwargs): + return self.attributes.items(*args, **kwargs) + + def get(self, *args, **kwargs): + return self.attributes.get(*args, **kwargs) + + def to_dict(self): + self.retrieve() + return self.attributes + + def retrieve(self, *args, **kwargs): + if not self.retrieved: + self._retrieve(*args, **kwargs) + self.retrieved = True + return self + + def _retrieve(self, *args, **kwargs): + url = self.url(action='get', params=self.attributes) + response = perform_request('get', url, self.default_retrieve_params) + self.update_attributes(**response) + + @classmethod + def find(cls, id): + return cls(id=id) + + def update_attributes(self, *args, **kwargs): + for k, v in kwargs.items(): + if k in self.accessible_fields: + self.__setattr__(k, v) + else: + raise AttributeError("Field {0} does not exist".format(k)) + + def updatable_attributes(self): + return extract(self.attributes, self.updatable_fields) + + def initializable_attributes(self): + return extract(self.attributes, self.initializable_fields) + + @classmethod + def before_save(cls, instance): + pass + + @classmethod + def after_save(cls, instance): + pass + + def save(self): + self.__class__.before_save(self) + if self.id: # if we have id already, treat this as an update + url = self.url(action='put', params=self.attributes) + response = perform_request('put', url, self.updatable_attributes()) + else: # otherwise, treat this as an insert + url = self.url(action='post', params=self.attributes) + response = perform_request('post', url, self.initializable_attributes()) + self.retrieved = True + self.update_attributes(**response) + self.__class__.after_save(self) + + def delete(self): + url = self.url(action='delete', params=self.attributes) + response = perform_request('delete', url) + self.retrieved = True + self.update_attributes(**response) + + @classmethod + def url_with_id(cls, params={}): + return cls.base_url + '/' + str(params['id']) + + @classmethod + def url_without_id(cls, params={}): + return cls.base_url + + @classmethod + def url(cls, action, params={}): + if cls.base_url is None: + raise CommentClientError("Must provide base_url when using default url function") + if action not in cls.DEFAULT_ACTIONS: + raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) + elif action in cls.DEFAULT_ACTIONS_WITH_ID: + try: + return cls.url_with_id(params) + except KeyError: + raise CommentClientError("Cannot perform action {0} without id".format(action)) + else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now + return cls.url_without_id() From 53257a3c478b8c01603365b70d465a61e4747d4c Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 15 Mar 2013 12:47:28 -0400 Subject: [PATCH 5/6] i need more sleep: --- common/models.py | 131 ----------------------------------------------- 1 file changed, 131 deletions(-) delete mode 100644 common/models.py diff --git a/common/models.py b/common/models.py deleted file mode 100644 index 2a8992554d..0000000000 --- a/common/models.py +++ /dev/null @@ -1,131 +0,0 @@ -from utils import * - - -class Model(object): - - accessible_fields = ['id'] - updatable_fields = ['id'] - initializable_fields = ['id'] - base_url = None - default_retrieve_params = {} - - DEFAULT_ACTIONS_WITH_ID = ['get', 'put', 'delete'] - DEFAULT_ACTIONS_WITHOUT_ID = ['get_all', 'post'] - DEFAULT_ACTIONS = DEFAULT_ACTIONS_WITH_ID + DEFAULT_ACTIONS_WITHOUT_ID - - def __init__(self, *args, **kwargs): - self.attributes = extract(kwargs, self.accessible_fields) - self.retrieved = False - - def __getattr__(self, name): - if name == 'id': - return self.attributes.get('id', None) - try: - return self.attributes[name] - except KeyError: - if self.retrieved or self.id is None: - raise AttributeError("Field {0} does not exist".format(name)) - self.retrieve() - return self.__getattr__(name) - - def __setattr__(self, name, value): - if name == 'attributes' or name not in self.accessible_fields: - super(Model, self).__setattr__(name, value) - else: - self.attributes[name] = value - - def __getitem__(self, key): - if key not in self.accessible_fields: - raise KeyError("Field {0} does not exist".format(key)) - return self.attributes.get(key) - - def __setitem__(self, key, value): - if key not in self.accessible_fields: - raise KeyError("Field {0} does not exist".format(key)) - self.attributes.__setitem__(key, value) - - def items(self, *args, **kwargs): - return self.attributes.items(*args, **kwargs) - - def get(self, *args, **kwargs): - return self.attributes.get(*args, **kwargs) - - def to_dict(self): - self.retrieve() - return self.attributes - - def retrieve(self, *args, **kwargs): - if not self.retrieved: - self._retrieve(*args, **kwargs) - self.retrieved = True - return self - - def _retrieve(self, *args, **kwargs): - url = self.url(action='get', params=self.attributes) - response = perform_request('get', url, self.default_retrieve_params) - self.update_attributes(**response) - - @classmethod - def find(cls, id): - return cls(id=id) - - def update_attributes(self, *args, **kwargs): - for k, v in kwargs.items(): - if k in self.accessible_fields: - self.__setattr__(k, v) - else: - raise AttributeError("Field {0} does not exist".format(k)) - - def updatable_attributes(self): - return extract(self.attributes, self.updatable_fields) - - def initializable_attributes(self): - return extract(self.attributes, self.initializable_fields) - - @classmethod - def before_save(cls, instance): - pass - - @classmethod - def after_save(cls, instance): - pass - - def save(self): - self.__class__.before_save(self) - if self.id: # if we have id already, treat this as an update - url = self.url(action='put', params=self.attributes) - response = perform_request('put', url, self.updatable_attributes()) - else: # otherwise, treat this as an insert - url = self.url(action='post', params=self.attributes) - response = perform_request('post', url, self.initializable_attributes()) - self.retrieved = True - self.update_attributes(**response) - self.__class__.after_save(self) - - def delete(self): - url = self.url(action='delete', params=self.attributes) - response = perform_request('delete', url) - self.retrieved = True - self.update_attributes(**response) - - @classmethod - def url_with_id(cls, params={}): - return cls.base_url + '/' + str(params['id']) - - @classmethod - def url_without_id(cls, params={}): - return cls.base_url - - @classmethod - def url(cls, action, params={}): - if cls.base_url is None: - raise CommentClientError("Must provide base_url when using default url function") - if action not in cls.DEFAULT_ACTIONS: - raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) - elif action in cls.DEFAULT_ACTIONS_WITH_ID: - try: - return cls.url_with_id(params) - except KeyError: - raise CommentClientError("Cannot perform action {0} without id".format(action)) - else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now - return cls.url_without_id() From a4451bdcd269341a82ce8280fe9148e38460c6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s=20Rocha?= Date: Fri, 15 Mar 2013 10:29:30 -0700 Subject: [PATCH 6/6] XBlock SDK announcement LMS Lighthouse [#261] --- lms/templates/feed.rss | 31 +++++---- .../press_releases/xblock_announcement.html | 63 +++++++++++++++++++ lms/urls.py | 6 +- 3 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 lms/templates/static_templates/press_releases/xblock_announcement.html diff --git a/lms/templates/feed.rss b/lms/templates/feed.rss index 37c7a8ce6e..a6fda0d20a 100644 --- a/lms/templates/feed.rss +++ b/lms/templates/feed.rss @@ -4,9 +4,18 @@ tag:www.edx.org,2012:/blog - ## + EdX Blog - 2013-03-14T14:00:12-07:00 + 2013-03-15T14:00:12-07:00 + + tag:www.edx.org,2013:Post/16 + 2013-03-15T10:00:00-07:00 + 2013-03-15T10:00:00-07:00 + + edX releases XBlock SDK, first step toward open source vision + <img src="${static.url('images/press/releases/edx-logo_240x180.png')}" /> + <p></p> + tag:www.edx.org,2013:Post/15 2013-03-14T10:00:00-07:00 @@ -16,15 +25,15 @@ <img src="${static.url('images/press/releases/201x_240x180.jpg')}" /> <p></p> - - tag:www.edx.org,2013:Post/14 - 2013-02-20T10:00:00-07:00 - 2013-02-20T10:00:00-07:00 - - edX Expands Internationally and Doubles its Institutional Membership with the Addition of Six New Schools - <img src="${static.url('images/press/releases/edx-logo_240x180.png')}" /> - <p></p> - + + + + + + + + + tag:www.edx.org,2013:Post/14 2013-01-30T10:00:00-07:00 diff --git a/lms/templates/static_templates/press_releases/xblock_announcement.html b/lms/templates/static_templates/press_releases/xblock_announcement.html new file mode 100644 index 0000000000..e6deaae23c --- /dev/null +++ b/lms/templates/static_templates/press_releases/xblock_announcement.html @@ -0,0 +1,63 @@ +<%! from django.core.urlresolvers import reverse %> +<%inherit file="../../main.html" /> + +<%namespace name='static' file='../../static_content.html'/> + +<%block name="title">edX Takes First Step toward Open Source Vision by Releasing XBlock SDK +
+ + +
+
+

edX Takes First Step toward Open Source Vision by Releasing XBlock SDK

+
+
+

With Release of XBlock Source Code, Global Community Invited to Participate in the Development of the edX Learning Platform and the Next Generation of Online and Blended Courses

+ +

CAMBRIDGE, MA and SANTA CLARA, CA (PyCon 2013) – March 14, 2013 – EdX, the not-for-profit online learning enterprise founded by Harvard University and the Massachusetts Institute of Technology (MIT), today released its XBlock SDK to the general public under the Affero GPL open source license. XBlock is the underlying architecture supporting the rich, interactive course content found in edX courses. With XBlock, educational institutions are able to go far beyond simple text and videos to deliver interactive learning built specifically for the Internet environment. The release of the XBlock source code marks the first step toward edX’s vision of creating an open online learning platform that mirrors the collaborative philosophy of MOOCs themselves and is an invitation to the global community of developers to work with edX to deliver the world’s best and most accessible online learning experience.

+ +

XBlock is a component architecture that enables developers to create independent course components, or XBlocks, that are able to work seamlessly with other components in the construction and presentation of an online course. Course authors are able to combine XBlocks from a variety of sources – from text and video to sophisticated wiki-based collaborative learning environments and online laboratories – to create rich engaging online courses. The XBlock architecture will enable the easy integration of next generation education tools like the circuit simulator in edX’s popular Circuits and Electronics course (6.002x) and the molecular manipulator in the new Introduction to Biology – The Secret of Life course (7.00x) taught by Eric Lander, one of the leaders of the Human Genome Project.

+ +

XBlock is not limited to just delivering courses. A complete educational ecosystem will make use of a number of web applications, all of which require access to course content and data. XBlocks provide the structure and APIs needed to build components for use by those applications. edX will be working with independent developers to continue to extend the functionality of XBlock through the XBlock SDK and future open source initiatives.

+ +

“From its beginning, edX has been committed to developing the world’s best learning platform and tapping our global community to help us get there,” said Rob Rubin, edX Vice President of Engineering. “We look forward to working with the world’s developers, educators and researchers to help evolve the platform and ensure that everyone, everywhere has access to the world-class education that edX provides.”

+ +

The XBlock source code is available immediately and can be accessed at http://github.com/edX/XBlock.

+ +

About edX

+ +

EdX is a not-for-profit enterprise of its founding partners Harvard University and the Massachusetts Institute of Technology focused on transforming online and on-campus learning through groundbreaking methodologies, game-like experiences and cutting-edge research. EdX provides inspirational and transformative knowledge to students of all ages, social status, and income who form worldwide communities of learners. EdX uses its open source technology to transcend physical and social borders. We’re focused on people, not profit. EdX is based in Cambridge, Massachusetts in the USA.

+ +
+

Media Contacts:

+

Dan O'Connell

+

oconnell@edx.org

+

(617) 480-6585

+
+

Gerald Kimber White

+

gerald.kimberwhite@rfbinder.com

+

781-455-8250

+
+ + +
+
+
diff --git a/lms/urls.py b/lms/urls.py index 2c738913c3..ee213f2b8c 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -172,11 +172,13 @@ urlpatterns = ('', url(r'^press/edx-expands-internationally$', 'static_template_view.views.render', {'template': 'press_releases/edx_expands_internationally.html'}, name="press/edx-expands-internationally"), - + url(r'^press/xblock_announcement$', 'static_template_view.views.render', + {'template': 'press_releases/xblock_announcement.html'}, + name="press/xblock-announcement"), # Should this always update to point to the latest press release? (r'^pressrelease$', 'django.views.generic.simple.redirect_to', - {'url': '/press/edx-expands-internationally'}), + {'url': '/press/xblock-announcement'}), (r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/images/favicon.ico'}),