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
e75f7950
Commit
e75f7950
authored
Nov 17, 2015
by
Bill DeRusha
Committed by
Peter Fogg
Feb 03, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updates XBlock renders its own template. Adds expand and collapse JS + jasmine tests.
ECOM-2809
parent
75bef91e
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
247 additions
and
34 deletions
+247
-34
cms/djangoapps/contentstore/course_info_model.py
+1
-13
cms/djangoapps/contentstore/views/tests/test_course_updates.py
+2
-3
cms/templates/course_info.html
+1
-1
common/lib/xmodule/xmodule/html_module.py
+39
-9
lms/static/js/courseware/toggle_element_visibility.js
+42
-0
lms/static/js/fixtures/courseware/course_updates.html
+45
-0
lms/static/js/spec/courseware/updates_visibility.js
+36
-0
lms/static/js/spec/main.js
+1
-0
lms/static/sass/course/_info.scss
+35
-1
lms/templates/courseware/course_updates.html
+29
-0
lms/templates/courseware/info.html
+4
-0
openedx/core/djangoapps/user_api/accounts/image_helpers.py
+12
-7
No files found.
cms/djangoapps/contentstore/course_info_model.py
View file @
e75f7950
...
...
@@ -160,25 +160,13 @@ def _get_index(passed_id=None):
return
0
def
_get_html
(
course_updates_items
):
"""
Method to create course_updates_html from course_updates items
"""
list_items
=
[]
for
update
in
reversed
(
course_updates_items
):
# filter course update items which have status "deleted".
if
update
.
get
(
"status"
)
!=
CourseInfoModule
.
STATUS_DELETED
:
list_items
.
append
(
u"<article><h2>{date}</h2>{content}</article>"
.
format
(
**
update
))
return
u"<section>{list_items}</section>"
.
format
(
list_items
=
""
.
join
(
list_items
))
def
save_course_update_items
(
location
,
course_updates
,
course_update_items
,
user
=
None
):
"""
Save list of course_updates data dictionaries in new field ("course_updates.items")
and html related to course update in 'data' ("course_updates.data") field.
"""
course_updates
.
items
=
course_update_items
course_updates
.
data
=
_get_html
(
course_update_items
)
course_updates
.
data
=
""
# update db record
modulestore
()
.
update_item
(
course_updates
,
user
.
id
)
...
...
cms/djangoapps/contentstore/views/tests/test_course_updates.py
View file @
e75f7950
...
...
@@ -173,9 +173,8 @@ class CourseUpdateTest(CourseTestCase):
self
.
assertHTMLEqual
(
update_content
,
json
.
loads
(
resp
.
content
)[
'content'
])
course_updates
=
modulestore
()
.
get_item
(
location
)
self
.
assertEqual
(
course_updates
.
items
,
[{
u'date'
:
update_date
,
u'content'
:
update_content
,
u'id'
:
1
}])
# course_updates 'data' field should update accordingly
update_data
=
u"<section><article><h2>{date}</h2>{content}</article></section>"
.
format
(
date
=
update_date
,
content
=
update_content
)
self
.
assertEqual
(
course_updates
.
data
,
update_data
)
# course_updates 'data' field should not update automatically
self
.
assertEqual
(
course_updates
.
data
,
''
)
# test delete course update item (soft delete)
course_updates
=
modulestore
()
.
get_item
(
location
)
...
...
cms/templates/course_info.html
View file @
e75f7950
...
...
@@ -27,7 +27,7 @@ from openedx.core.lib.js_utils import escape_json_dumps
"${handouts_locator | escapejs}",
"${base_asset_url}",
${escape_json_dumps(push_notification_enabled) | n}
);
);
});
</
%
block>
...
...
common/lib/xmodule/xmodule/html_module.py
View file @
e75f7950
import
os
import
sys
import
re
import
copy
from
datetime
import
datetime
from
fs.errors
import
ResourceNotFoundError
import
logging
import
textwrap
from
lxml
import
etree
import
os
from
path
import
Path
as
path
from
fs.errors
import
ResourceNotFoundError
from
pkg_resources
import
resource_string
import
re
import
sys
import
textwrap
import
dogstats_wrapper
as
dog_stats_api
from
xmodule.util.misc
import
escape_html_characters
...
...
@@ -75,10 +76,10 @@ class HtmlBlock(object):
return
Fragment
(
self
.
get_html
())
def
get_html
(
self
):
"""
When we switch this to an XBlock, we can merge this with student_view,
but for now the XModule mixin requires that this method be defined.
"""
"""
Returns html required for rendering XModule. """
# When we switch this to an XBlock, we can merge this with student_view,
# but for now the XModule mixin requires that this method be defined.
# pylint: disable=no-member
if
self
.
system
.
anonymous_student_id
:
return
self
.
data
.
replace
(
"
%%
USER_ID
%%
"
,
self
.
system
.
anonymous_student_id
)
...
...
@@ -417,6 +418,35 @@ class CourseInfoModule(CourseInfoFields, HtmlModuleMixin):
# statuses
STATUS_VISIBLE
=
'visible'
STATUS_DELETED
=
'deleted'
TEMPLATE_DIR
=
'courseware'
@XBlock.supports
(
"multi_device"
)
def
student_view
(
self
,
_context
):
"""
Return a fragment that contains the html for the student view
"""
return
Fragment
(
self
.
get_html
())
def
get_html
(
self
):
""" Returns html required for rendering XModule. """
# When we switch this to an XBlock, we can merge this with student_view,
# but for now the XModule mixin requires that this method be defined.
# pylint: disable=no-member
if
self
.
data
!=
""
:
if
self
.
system
.
anonymous_student_id
:
return
self
.
data
.
replace
(
"
%%
USER_ID
%%
"
,
self
.
system
.
anonymous_student_id
)
return
self
.
data
else
:
course_updates
=
[
item
for
item
in
self
.
items
if
item
.
get
(
'status'
)
==
self
.
STATUS_VISIBLE
]
course_updates
.
sort
(
key
=
lambda
item
:
datetime
.
strptime
(
item
[
'date'
],
'
%
B
%
d,
%
Y'
),
reverse
=
True
)
context
=
{
'visible_updates'
:
course_updates
[:
3
],
'hidden_updates'
:
course_updates
[
3
:],
}
return
self
.
system
.
render_template
(
"{0}/course_updates.html"
.
format
(
self
.
TEMPLATE_DIR
),
context
)
@XBlock.tag
(
"detached"
)
...
...
lms/static/js/courseware/toggle_element_visibility.js
0 → 100644
View file @
e75f7950
;(
function
(
define
)
{
'use strict'
;
define
([
"jquery"
],
function
(
$
)
{
return
function
()
{
// define variables for code legibility
var
toggleActionElements
=
$
(
'.toggle-visibility-button'
);
var
updateToggleActionText
=
function
(
targetElement
,
actionElement
)
{
var
show_text
=
actionElement
.
data
(
'show'
);
var
hide_text
=
actionElement
.
data
(
'hide'
);
if
(
targetElement
.
is
(
":visible"
))
{
if
(
hide_text
)
{
actionElement
.
html
(
actionElement
.
data
(
'hide'
));
}
else
{
actionElement
.
hide
();
}
}
else
{
if
(
show_text
)
{
actionElement
.
html
(
actionElement
.
data
(
'show'
));
}
}
};
$
.
each
(
toggleActionElements
,
function
(
i
,
elem
)
{
var
toggleActionElement
=
$
(
elem
);
var
toggleTargetElement
=
toggleActionElement
.
siblings
(
'.toggle-visibility-element'
);
updateToggleActionText
(
toggleTargetElement
,
toggleActionElement
);
toggleActionElement
.
on
(
'click'
,
function
(
event
)
{
event
.
preventDefault
();
toggleTargetElement
.
toggleClass
(
'hidden'
);
updateToggleActionText
(
toggleTargetElement
,
toggleActionElement
);
});
});
};
});
})(
define
||
RequireJS
.
define
);
lms/static/js/fixtures/courseware/course_updates.html
0 → 100644
View file @
e75f7950
<div
class=
"recent-updates"
>
<article>
<h2
class=
"date"
>
December 1, 2015
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"Hide"
data-show=
"Show"
>
Hide
</a>
<div
class=
"toggle-visibility-element article-content "
>
<h1>
Assignment 1
</h1>
<p>
Please submit your first assignment before due date.
</p>
</div>
</article>
<article>
<h2
class=
"date"
>
December 1, 2015
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"Hide"
data-show=
"Show"
>
Show
</a>
<div
class=
"toggle-visibility-element article-content"
>
<h1>
Quiz 1
</h1>
<p>
You have a quiz due on coming friday.
</p>
</div>
</article>
<article>
<h2
class=
"date"
>
November 26, 2015
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"Hide"
data-show=
"Show"
>
Show
</a>
<div
class=
"toggle-visibility-element article-content hidden"
>
<h1>
Assignment update
</h1>
<p>
Please submit your first assignment before due date.
</p>
</div>
</article>
</div>
<div
class=
"old-updates hidden toggle-visibility-element"
>
<article>
<h2
class=
"date"
>
November 20, 2015
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"Hide"
data-show=
"Show"
>
Show
</a>
<div
class=
"toggle-visibility-element article-content hidden"
><h1>
Orientation
</h1>
<p>
Orientation will held on monday
</p>
</div>
</article>
<article>
<h2
class=
"date"
>
November 19, 2015
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"Hide"
data-show=
"Show"
>
Show
</a>
<div
class=
"toggle-visibility-element article-content hidden"
><h1>
Course starting
</h1>
<p>
Starting info about course.
</p>
</div>
</article>
</div>
<a
class=
"toggle-visibility-button show-older-updates"
data-hide=
""
data-show=
"Show Earlier Course Updates"
>
Show Earlier Course Updates
</a>
lms/static/js/spec/courseware/updates_visibility.js
0 → 100644
View file @
e75f7950
define
([
'jquery'
,
'js/courseware/toggle_element_visibility'
],
function
(
$
,
ToggleElementVisibility
)
{
'use strict'
;
describe
(
'show/hide with mouse click'
,
function
()
{
beforeEach
(
function
()
{
loadFixtures
(
'js/fixtures/courseware/course_updates.html'
);
/*jshint newcap: false */
ToggleElementVisibility
();
/*jshint newcap: true */
});
it
(
'ensures update will hide on hide button click'
,
function
()
{
var
$shownUpdate
=
$
(
'.toggle-visibility-element:not(.hidden)'
).
first
();
$shownUpdate
.
siblings
(
'.toggle-visibility-button'
).
trigger
(
'click'
);
expect
(
$shownUpdate
).
toHaveClass
(
'hidden'
);
});
it
(
'ensures update will show on show button click'
,
function
()
{
var
$hiddenUpdate
=
$
(
'.toggle-visibility-element.hidden'
).
first
();
$hiddenUpdate
.
siblings
(
'.toggle-visibility-button'
).
trigger
(
'click'
);
expect
(
$hiddenUpdate
).
not
.
toHaveClass
(
'hidden'
);
});
it
(
'ensures old updates will show on button click'
,
function
()
{
// on page load old updates will be hidden
var
$oldUpdates
=
$
(
'.toggle-visibility-element.old-updates'
);
expect
(
$oldUpdates
).
toHaveClass
(
'hidden'
);
// on click on show earlier update button old updates will be shown
$
(
'.toggle-visibility-button.show-older-updates'
).
trigger
(
'click'
);
expect
(
$oldUpdates
).
not
.
toHaveClass
(
'hidden'
);
});
});
});
lms/static/js/spec/main.js
View file @
e75f7950
...
...
@@ -708,6 +708,7 @@
'lms/include/js/spec/edxnotes/collections/notes_spec.js'
,
'lms/include/js/spec/search/search_spec.js'
,
'lms/include/js/spec/navigation_spec.js'
,
'lms/include/js/spec/courseware/updates_visibility.js'
,
'lms/include/js/spec/discovery/collections/filters_spec.js'
,
'lms/include/js/spec/discovery/models/course_card_spec.js'
,
'lms/include/js/spec/discovery/models/course_directory_spec.js'
,
...
...
lms/static/sass/course/_info.scss
View file @
e75f7950
...
...
@@ -50,6 +50,8 @@ div.info-wrapper {
@extend
.content
;
@include
padding-left
(
$baseline
);
line-height
:
lh
();
width
:
100%
;
display
:
block
;
h1
{
@include
text-align
(
left
);
...
...
@@ -69,6 +71,25 @@ div.info-wrapper {
margin-bottom
:
lh
();
padding-left
:
0
;
.updates-article
{
border-radius
:
3px
;
background-color
:
$white
;
border
:
1px
solid
transparent
;
&
:hover
{
border
:
1px
solid
$gray-l3
;
}
}
.show-older-updates
{
@extend
%btn-pl-white-base
;
padding
:
(
$baseline
/
2
);
@include
font-size
(
14
);
width
:
100%
;
display
:
block
;
text-align
:
center
;
cursor
:
pointer
;
}
>
li
,
article
{
@extend
.clearfix
;
padding
:
$baseline
;
...
...
@@ -81,12 +102,25 @@ div.info-wrapper {
}
}
h2
{
h2
.date
{
@extend
%t-title9
;
margin-bottom
:
(
$baseline
/
4
);
text-transform
:
none
;
background
:
url('
#{
$static-path
}
/images/calendar-icon.png')
0
center
no-repeat
;
@include
padding-left
(
$baseline
);
@include
float
(
left
);
}
.toggle-visibility-button
{
@extend
%t-title9
;
@include
float
(
right
);
cursor
:
pointer
;
}
.toggle-visibility-element
{
content
:
''
;
display
:block
;
clear
:
both
;
}
section
.update-description
{
...
...
lms/templates/courseware/course_updates.html
0 → 100644
View file @
e75f7950
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<section>
<div
class=
"recent-updates"
>
% for index, update in enumerate(visible_updates):
<article
class=
"updates-article"
>
% if not update.get("is_error"):
<h2
class=
"date"
>
${update.get("date")}
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"${_('Hide')}"
data-show=
"${_('Show')}"
></a>
% endif
<div
class=
"toggle-visibility-element article-content ${'hidden' if index >= 1 else ''}"
>
${update.get("content")}
</div>
</article>
% endfor
</div>
<div
class=
"old-updates hidden toggle-visibility-element"
>
% for update in hidden_updates:
<article
class=
"updates-article"
>
<h2
class=
"date"
>
${update.get("date")}
</h2>
<a
class=
"toggle-visibility-button"
data-hide=
"${_('Hide')}"
data-show=
"${_('Show')}"
></a>
<div
class=
"toggle-visibility-element article-content hidden"
>
${update.get("content")}
</div>
</article>
% endfor
</div>
% if len(hidden_updates) > 0:
<a
class=
"toggle-visibility-button show-older-updates"
data-hide=
""
data-show=
"${_('Show Earlier Course Updates')}"
></a>
% endif
</section>
lms/templates/courseware/info.html
View file @
e75f7950
...
...
@@ -34,6 +34,10 @@ from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
<
%
include
file=
"/courseware/course_navigation.html"
args=
"active_page='info'"
/>
<
%
static:require_module
module_name=
"js/courseware/toggle_element_visibility"
class_name=
"ToggleElementVisibility"
>
ToggleElementVisibility();
</
%
static:require
_module
>
<
%
block
name=
"bodyclass"
>
view-in-course view-course-info ${course.css_class or ''}
</
%
block>
<section
class=
"container"
>
<div
class=
"home"
>
...
...
openedx/core/djangoapps/user_api/accounts/image_helpers.py
View file @
e75f7950
...
...
@@ -92,13 +92,18 @@ def get_profile_image_urls_for_user(user, request=None):
dictionary of {size_display_name: url} for each image.
"""
if
user
.
profile
.
has_profile_image
:
urls
=
_get_profile_image_urls
(
_make_profile_image_name
(
user
.
username
),
get_profile_image_storage
(),
version
=
user
.
profile
.
profile_image_uploaded_at
.
strftime
(
"
%
s"
),
)
else
:
try
:
if
user
.
profile
.
has_profile_image
:
urls
=
_get_profile_image_urls
(
_make_profile_image_name
(
user
.
username
),
get_profile_image_storage
(),
version
=
user
.
profile
.
profile_image_uploaded_at
.
strftime
(
"
%
s"
),
)
else
:
urls
=
_get_default_profile_image_urls
()
except
UserProfile
.
DoesNotExist
:
# when user does not have profile it raises exception, when exception
# occur we can simply get default image.
urls
=
_get_default_profile_image_urls
()
if
request
:
...
...
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