Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
b06d5bed
Commit
b06d5bed
authored
Apr 25, 2017
by
Andy Armstrong
Committed by
GitHub
Apr 25, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14953 from edx/andy/course-updates-page
Implement new course updates page
parents
a0129ccb
6b8b79ff
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
225 additions
and
6 deletions
+225
-6
lms/djangoapps/courseware/tabs.py
+1
-1
lms/static/sass/shared-v2/_components.scss
+7
-0
openedx/features/course_bookmarks/views/course_bookmarks.py
+0
-1
openedx/features/course_experience/templates/course_experience/course-home-fragment.html
+6
-0
openedx/features/course_experience/templates/course_experience/course-updates-fragment.html
+42
-0
openedx/features/course_experience/tests/views/test_course_home.py
+1
-1
openedx/features/course_experience/tests/views/test_course_updates.py
+90
-0
openedx/features/course_experience/urls.py
+14
-3
openedx/features/course_experience/views/course_updates.py
+64
-0
No files found.
lms/djangoapps/courseware/tabs.py
View file @
b06d5bed
...
...
@@ -45,7 +45,7 @@ class CoursewareTab(EnrolledTab):
Returns the main course URL for the current user.
"""
if
waffle
.
flag_is_active
(
request
,
UNIFIED_COURSE_VIEW_FLAG
):
return
'edx.course_experience.course_home'
return
'
open
edx.course_experience.course_home'
else
:
return
'courseware'
...
...
lms/static/sass/shared-v2/_components.scss
View file @
b06d5bed
...
...
@@ -150,6 +150,13 @@
}
}
.section
{
.icon
{
width
:
20px
;
text-align
:
center
;
}
}
.section
:not
(
:first-child
)
{
margin-top
:
$baseline
;
}
openedx/features/course_bookmarks/views/course_bookmarks.py
View file @
b06d5bed
...
...
@@ -18,7 +18,6 @@ from opaque_keys.edx.keys import CourseKey
from
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
util.views
import
ensure_valid_course_key
from
web_fragments.fragment
import
Fragment
from
xmodule.modulestore.django
import
modulestore
class
CourseBookmarksView
(
View
):
...
...
openedx/features/course_experience/templates/course_experience/course-home-fragment.html
View file @
b06d5bed
...
...
@@ -74,6 +74,12 @@ from openedx.features.course_experience import UNIFIED_COURSE_EXPERIENCE_FLAG
${_("Bookmarks")}
</a>
</li>
<li>
<a
class=
"action-show-bookmarks"
href=
"${reverse('openedx.course_experience.course_updates', args=[course.id])}"
>
<span
class=
"icon fa fa-newspaper-o"
aria-hidden=
"true"
></span>
${_("Updates")}
</a>
</li>
</ul>
</div>
% if handouts_html:
...
...
openedx/features/course_experience/templates/course_experience/course-updates-fragment.html
0 → 100644
View file @
b06d5bed
## mako
<
%
page
expression_filter=
"h"
/>
<
%
namespace
name=
'static'
file=
'../static_content.html'
/>
<
%!
import
json
from
django
.
conf
import
settings
from
django
.
utils
.
translation
import
ugettext
as
_
from
django
.
template
.
defaultfilters
import
escapejs
from
django
.
core
.
urlresolvers
import
reverse
from
django_comment_client
.
permissions
import
has_permission
from
openedx
.
core
.
djangolib
.
js_utils
import
dump_js_escaped_json
,
js_escaped_string
from
openedx
.
core
.
djangolib
.
markup
import
HTML
from
openedx
.
features
.
course_experience
import
UNIFIED_COURSE_EXPERIENCE_FLAG
%
>
<
%
block
name=
"content"
>
<div
class=
"course-updates container"
id=
"course-container"
>
<header
class=
"page-header has-secondary"
>
## Breadcrumb navigation
<div
class=
"page-header-main"
>
<nav
aria-label=
"${_('Course Updates')}"
class=
"sr-is-focusable"
tabindex=
"-1"
>
<div
class=
"has-breadcrumbs"
>
<div
class=
"breadcrumbs"
>
<span
class=
"nav-item"
>
<a
href=
"${course_url}"
>
Course
</a>
</span>
<span
class=
"icon fa fa-angle-right"
aria-hidden=
"true"
></span>
<span
class=
"nav-item"
>
${_('Course Updates')}
</span>
</div>
</div>
</nav>
</div>
</header>
<div
class=
"page-content"
>
${HTML(updates_html)}
</div>
</div>
</
%
block>
openedx/features/course_experience/tests/views/test_course_home.py
View file @
b06d5bed
...
...
@@ -18,7 +18,7 @@ def course_home_url(course):
Returns the URL for the course's home page
"""
return
reverse
(
'edx.course_experience.course_home'
,
'
open
edx.course_experience.course_home'
,
kwargs
=
{
'course_id'
:
unicode
(
course
.
id
),
}
...
...
openedx/features/course_experience/tests/views/test_course_updates.py
0 → 100644
View file @
b06d5bed
"""
Tests for the course updates page.
"""
from
django.core.urlresolvers
import
reverse
from
student.models
import
CourseEnrollment
from
student.tests.factories
import
UserFactory
from
xmodule.html_module
import
CourseInfoModule
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.tests.django_utils
import
SharedModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
,
check_mongo_calls
TEST_PASSWORD
=
'test'
def
course_updates_url
(
course
):
"""
Returns the URL for the course's home page
"""
return
reverse
(
'openedx.course_experience.course_updates'
,
kwargs
=
{
'course_id'
:
unicode
(
course
.
id
),
}
)
class
TestCourseUpdatesPage
(
SharedModuleStoreTestCase
):
"""
Test the course updates page.
"""
@classmethod
def
setUpClass
(
cls
):
"""Set up the simplest course possible."""
# setUpClassAndTestData() already calls setUpClass on SharedModuleStoreTestCase
# pylint: disable=super-method-not-called
with
super
(
TestCourseUpdatesPage
,
cls
)
.
setUpClassAndTestData
():
with
cls
.
store
.
default_store
(
ModuleStoreEnum
.
Type
.
split
):
cls
.
course
=
CourseFactory
.
create
()
with
cls
.
store
.
bulk_operations
(
cls
.
course
.
id
):
# Create a basic course structure
chapter
=
ItemFactory
.
create
(
category
=
'chapter'
,
parent_location
=
cls
.
course
.
location
)
section
=
ItemFactory
.
create
(
category
=
'sequential'
,
parent_location
=
chapter
.
location
)
ItemFactory
.
create
(
category
=
'vertical'
,
parent_location
=
section
.
location
)
@classmethod
def
setUpTestData
(
cls
):
"""Set up and enroll our fake user in the course."""
cls
.
user
=
UserFactory
(
password
=
TEST_PASSWORD
)
CourseEnrollment
.
enroll
(
cls
.
user
,
cls
.
course
.
id
)
# Create course updates
cls
.
create_course_updates
(
cls
.
course
,
cls
.
user
)
@classmethod
def
create_course_updates
(
cls
,
course
,
user
,
count
=
5
):
"""
Create some test course updates.
"""
updates_usage_key
=
course
.
id
.
make_usage_key
(
'course_info'
,
'updates'
)
course_updates
=
modulestore
()
.
create_item
(
user
.
id
,
updates_usage_key
.
course_key
,
updates_usage_key
.
block_type
,
block_id
=
updates_usage_key
.
block_id
)
course_updates
.
data
=
u'<ol><li><a href="test">Test Update</a></li></ol>'
modulestore
()
.
update_item
(
course_updates
,
user
.
id
)
def
setUp
(
self
):
"""
Set up for the tests.
"""
super
(
TestCourseUpdatesPage
,
self
)
.
setUp
()
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
TEST_PASSWORD
)
def
test_view
(
self
):
url
=
course_updates_url
(
self
.
course
)
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
response_content
=
response
.
content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'<a href="test">Test Update</a>'
,
response_content
)
def
test_queries
(
self
):
# Fetch the view and verify that the query counts haven't changed
with
self
.
assertNumQueries
(
34
):
with
check_mongo_calls
(
4
):
url
=
course_updates_url
(
self
.
course
)
self
.
client
.
get
(
url
)
openedx/features/course_experience/urls.py
View file @
b06d5bed
...
...
@@ -6,21 +6,32 @@ from django.conf.urls import url
from
views.course_home
import
CourseHomeView
,
CourseHomeFragmentView
from
views.course_outline
import
CourseOutlineFragmentView
from
views.course_updates
import
CourseUpdatesFragmentView
,
CourseUpdatesView
urlpatterns
=
[
url
(
r'^$'
,
CourseHomeView
.
as_view
(),
name
=
'edx.course_experience.course_home'
,
name
=
'openedx.course_experience.course_home'
,
),
url
(
r'^updates$'
,
CourseUpdatesView
.
as_view
(),
name
=
'openedx.course_experience.course_updates'
,
),
url
(
r'^home_fragment$'
,
CourseHomeFragmentView
.
as_view
(),
name
=
'edx.course_experience.course_home_fragment_view'
,
name
=
'
open
edx.course_experience.course_home_fragment_view'
,
),
url
(
r'^outline_fragment$'
,
CourseOutlineFragmentView
.
as_view
(),
name
=
'edx.course_experience.course_outline_fragment_view'
,
name
=
'openedx.course_experience.course_outline_fragment_view'
,
),
url
(
r'^updates_fragment$'
,
CourseUpdatesFragmentView
.
as_view
(),
name
=
'openedx.course_experience.course_updates_fragment_view'
,
),
]
openedx/features/course_experience/views/course_updates.py
0 → 100644
View file @
b06d5bed
"""
Views that handle course updates.
"""
from
django.contrib.auth.decorators
import
login_required
from
django.core.context_processors
import
csrf
from
django.core.urlresolvers
import
reverse
from
django.template.loader
import
render_to_string
from
django.utils.decorators
import
method_decorator
from
django.views.decorators.cache
import
cache_control
from
courseware.courses
import
get_course_info_section
,
get_course_with_access
from
lms.djangoapps.courseware.tabs
import
CoursewareTab
from
lms.djangoapps.courseware.views.views
import
CourseTabView
from
opaque_keys.edx.keys
import
CourseKey
from
openedx.core.djangoapps.plugin_api.views
import
EdxFragmentView
from
web_fragments.fragment
import
Fragment
class
CourseUpdatesView
(
CourseTabView
):
"""
The course updates page.
"""
@method_decorator
(
login_required
)
@method_decorator
(
cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
))
def
get
(
self
,
request
,
course_id
,
**
kwargs
):
"""
Displays the home page for the specified course.
"""
return
super
(
CourseUpdatesView
,
self
)
.
get
(
request
,
course_id
,
'courseware'
,
**
kwargs
)
def
render_to_fragment
(
self
,
request
,
course
=
None
,
tab
=
None
,
**
kwargs
):
course_id
=
unicode
(
course
.
id
)
updates_fragment_view
=
CourseUpdatesFragmentView
()
return
updates_fragment_view
.
render_to_fragment
(
request
,
course_id
=
course_id
,
**
kwargs
)
class
CourseUpdatesFragmentView
(
EdxFragmentView
):
"""
A fragment to render the home page for a course.
"""
def
render_to_fragment
(
self
,
request
,
course_id
=
None
,
**
kwargs
):
"""
Renders the course's home page as a fragment.
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
,
check_if_enrolled
=
True
)
course_url_name
=
CoursewareTab
.
main_course_url_name
(
request
)
course_url
=
reverse
(
course_url_name
,
kwargs
=
{
'course_id'
:
unicode
(
course
.
id
)})
# Fetch the updates as HTML
updates_html
=
get_course_info_section
(
request
,
request
.
user
,
course
,
'updates'
)
# Render the course home fragment
context
=
{
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'course'
:
course
,
'course_url'
:
course_url
,
'updates_html'
:
updates_html
,
'disable_courseware_js'
:
True
,
'uses_pattern_library'
:
True
,
}
html
=
render_to_string
(
'course_experience/course-updates-fragment.html'
,
context
)
return
Fragment
(
html
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment