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
9b5285ad
Commit
9b5285ad
authored
Aug 27, 2012
by
Tom Giannattasio
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into feature/rocha/wiki-cheatsheet
parents
d1760f9a
25c83bbb
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
52 changed files
with
333 additions
and
170 deletions
+333
-170
common/djangoapps/mitxmako/middleware.py
+1
-1
common/djangoapps/student/models.py
+1
-1
common/djangoapps/student/views.py
+1
-1
common/lib/capa/capa/correctmap.py
+6
-4
common/lib/xmodule/xmodule/css/sequence/display.scss
+32
-23
common/lib/xmodule/xmodule/js/src/sequence/display.coffee
+1
-0
doc/xml-format.md
+0
-0
lms/djangoapps/courseware/courses.py
+8
-2
lms/djangoapps/courseware/module_render.py
+12
-6
lms/djangoapps/courseware/views.py
+6
-3
lms/djangoapps/django_comment_client/base/views.py
+18
-14
lms/djangoapps/django_comment_client/forum/views.py
+9
-9
lms/djangoapps/django_comment_client/utils.py
+25
-8
lms/envs/aws.py
+9
-2
lms/envs/common.py
+2
-0
lms/envs/dev_ike.py
+2
-0
lms/lib/comment_client/user.py
+0
-10
lms/static/coffee/src/discussion/content.coffee
+28
-9
lms/static/coffee/src/discussion/discussion.coffee
+9
-1
lms/static/coffee/src/discussion/discussion_module.coffee
+1
-1
lms/static/coffee/src/discussion/utils.coffee
+11
-6
lms/static/coffee/src/navigation.coffee
+8
-1
lms/static/js/jquery.gradebook.js
+35
-4
lms/static/js/jquery.sequence.js
+0
-5
lms/static/sass/_discussion.scss
+6
-0
lms/static/sass/course/_gradebook.scss
+13
-12
lms/static/sass/course/courseware/_courseware.scss
+1
-0
lms/static/sass/course/courseware/_sidebar.scss
+4
-0
lms/static/sass/course/layout/_courseware_header.scss
+35
-3
lms/static/sass/course/wiki/_wiki.scss
+5
-2
lms/static/sass/multicourse/_dashboard.scss
+12
-5
lms/templates/discussion/_content_renderer.html
+1
-1
lms/templates/discussion/_discussion_module.html
+1
-1
lms/templates/discussion/_forum.html
+1
-1
lms/templates/discussion/_inline.html
+1
-1
lms/templates/discussion/_paginator.html
+2
-2
lms/templates/discussion/_recent_active_posts.html
+1
-1
lms/templates/discussion/_search_bar.html
+2
-2
lms/templates/discussion/_similar_posts.html
+1
-1
lms/templates/discussion/_single_thread.html
+1
-1
lms/templates/discussion/_sort.html
+1
-1
lms/templates/discussion/_trending_tags.html
+1
-1
lms/templates/discussion/_user_active_threads.html
+1
-1
lms/templates/discussion/_user_profile.html
+3
-3
lms/templates/discussion/index.html
+1
-1
lms/templates/discussion/mustache/_content.mustache
+4
-7
lms/templates/discussion/user_profile.html
+2
-2
lms/templates/registration/password_reset_email.html
+1
-1
lms/templates/seq_module.html
+0
-3
lms/templates/wiki/article.html
+0
-2
lms/urls.py
+6
-3
repo-requirements.txt
+1
-1
No files found.
common/djangoapps/mitxmako/middleware.py
View file @
9b5285ad
...
...
@@ -46,4 +46,4 @@ class MakoMiddleware(object):
global
requestcontext
requestcontext
=
RequestContext
(
request
)
requestcontext
[
'is_secure'
]
=
request
.
is_secure
()
requestcontext
[
'site'
]
=
settings
.
SITE_NAME
requestcontext
[
'site'
]
=
request
.
get_host
()
common/djangoapps/student/models.py
View file @
9b5285ad
...
...
@@ -273,7 +273,7 @@ def add_user_to_default_group(user, group):
utg
.
users
.
add
(
User
.
objects
.
get
(
username
=
user
))
utg
.
save
()
#
@receiver(post_save, sender=User)
@receiver
(
post_save
,
sender
=
User
)
def
update_user_information
(
sender
,
instance
,
created
,
**
kwargs
):
try
:
cc_user
=
cc
.
User
.
from_django_user
(
instance
)
...
...
common/djangoapps/student/views.py
View file @
9b5285ad
...
...
@@ -511,7 +511,7 @@ def password_reset(request):
form
.
save
(
use_https
=
request
.
is_secure
(),
from_email
=
settings
.
DEFAULT_FROM_EMAIL
,
request
=
request
,
domain_override
=
settings
.
SITE_NAME
)
domain_override
=
request
.
get_host
()
)
return
HttpResponse
(
json
.
dumps
({
'success'
:
True
,
'value'
:
render_to_string
(
'registration/password_reset_done.html'
,
{})}))
else
:
...
...
common/lib/capa/capa/correctmap.py
View file @
9b5285ad
...
...
@@ -73,10 +73,12 @@ class CorrectMap(object):
return
answer_id
in
self
.
cmap
and
self
.
cmap
[
answer_id
][
'queuekey'
]
==
test_key
def
get_npoints
(
self
,
answer_id
):
if
self
.
is_correct
(
answer_id
):
npoints
=
self
.
cmap
[
answer_id
]
.
get
(
'npoints'
,
1
)
# default to 1 point if correct
return
npoints
or
1
return
0
# if not correct, return 0
npoints
=
self
.
get_property
(
answer_id
,
'npoints'
)
if
npoints
is
not
None
:
return
npoints
elif
self
.
is_correct
(
answer_id
):
return
1
return
0
# if not correct and no points have been assigned, return 0
def
set_property
(
self
,
answer_id
,
property
,
value
):
if
answer_id
in
self
.
cmap
:
self
.
cmap
[
answer_id
][
property
]
=
value
...
...
common/lib/xmodule/xmodule/css/sequence/display.scss
View file @
9b5285ad
...
...
@@ -61,13 +61,12 @@ nav.sequence-nav {
min-width
:
20px
;
a
{
width
:
34px
;
height
:
34
px
;
margin
:
4px
auto
;
background-position
:
center
1
0
px
;
width
:
100%
;
height
:
42
px
;
margin
:
0
;
background-position
:
center
1
4
px
;
background-repeat
:
no-repeat
;
border
:
1px
solid
transparent
;
@include
border-radius
(
35px
);
cursor
:
pointer
;
display
:
block
;
padding
:
0
;
...
...
@@ -82,7 +81,7 @@ nav.sequence-nav {
&
:hover
{
background-color
:
#fff
;
background-repeat
:
no-repeat
;
background-position
:
center
1
0
px
;
background-position
:
center
1
4
px
;
}
&
.active
{
...
...
@@ -103,7 +102,7 @@ nav.sequence-nav {
&
:hover
{
background-color
:
#fff
;
background-repeat
:
no-repeat
;
background-position
:
center
1
0
px
;
background-position
:
center
1
4
px
;
}
}
...
...
@@ -298,14 +297,16 @@ nav.sequence-bottom {
ul
{
@extend
.clearfix
;
border
:
1px
solid
$border-color
;
@include
border-radius
(
3px
);
@include
inline-block
();
width
:
10
0
px
;
width
:
10
3
px
;
li
{
float
:
left
;
width
:
50%
;
width
:
50px
;
height
:
44px
;
border
:
1px
solid
#ccc
;
@include
linear-gradient
(
top
,
#eee
,
#ddd
);
@include
box-shadow
(
0
1px
0
rgba
(
255
,
255
,
255
,
.7
)
inset
);
&
.prev
,
&
.next
{
margin-bottom
:
0
;
...
...
@@ -318,38 +319,39 @@ nav.sequence-bottom {
padding
:
lh
(
.5
)
4px
;
text-indent
:
-9999px
;
@include
transition
(
all
,
.2s
,
$ease-in-out-quad
);
outline
:
0
;
&
:hover
{
background-color
:
#ddd
;
color
:
#000
;
opacity
:
.5
;
text-decoration
:
none
;
background-position
:
center
15px
;
}
&
.disabled
{
opacity
:
.4
;
}
&
:focus
{
outline
:
0
;
}
}
}
&
.prev
{
border-radius
:
35px
0
0
35px
;
a
{
background-image
:
url('../images/sequence-nav/previous-icon.png')
;
border-right
:
1px
solid
lighten
(
#c6c6c6
,
10%
);
&
:hover
{
background-color
:
none
;
}
background-position
:
center
15px
;
}
}
&
.next
{
border-radius
:
0
35px
35px
0
;
border-left
:
none
;
a
{
background-image
:
url('../images/sequence-nav/next-icon.png')
;
&
:hover
{
background-color
:
none
;
}
background-position
:
center
15px
;
}
}
}
...
...
@@ -360,5 +362,12 @@ div.course-wrapper section.course-content ol.vert-mod > li ul.sequence-nav-butto
list-style
:
none
!
important
;
}
.xmodule_SequenceModule
nav
.sequence-bottom
ul
li
.next
a
,
.xmodule_SequenceModule
nav
.sequence-bottom
ul
li
.prev
a
{
outline
:
0
;
&
:focus
{
outline
:
0
;
}
}
common/lib/xmodule/xmodule/js/src/sequence/display.coffee
View file @
9b5285ad
...
...
@@ -55,6 +55,7 @@ class @Sequence
element
.
removeClass
(
'progress-none'
)
.
removeClass
(
'progress-some'
)
.
removeClass
(
'progress-done'
)
switch
progress
when
'none'
then
element
.
addClass
(
'progress-none'
)
when
'in_progress'
then
element
.
addClass
(
'progress-some'
)
...
...
doc/xml-format.md
View file @
9b5285ad
This diff is collapsed.
Click to expand it.
lms/djangoapps/courseware/courses.py
View file @
9b5285ad
...
...
@@ -5,6 +5,7 @@ import logging
from
path
import
path
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.http
import
Http404
from
xmodule.course_module
import
CourseDescriptor
...
...
@@ -133,8 +134,13 @@ def get_course_info_section(course, section_key):
if
section_key
in
[
'handouts'
,
'guest_handouts'
,
'updates'
,
'guest_updates'
]:
try
:
with
course
.
system
.
resources_fs
.
open
(
path
(
"info"
)
/
section_key
+
".html"
)
as
htmlFile
:
return
replace_urls
(
htmlFile
.
read
()
.
decode
(
'utf-8'
),
course
.
metadata
[
'data_dir'
])
# Replace '/static/' urls
info_html
=
replace_urls
(
htmlFile
.
read
()
.
decode
(
'utf-8'
),
course
.
metadata
[
'data_dir'
])
# Replace '/course/' urls
course_root
=
reverse
(
'course_root'
,
args
=
[
course
.
id
])[:
-
1
]
# Remove trailing slash
info_html
=
replace_urls
(
info_html
,
course_root
,
'/course/'
)
return
info_html
except
ResourceNotFoundError
:
log
.
exception
(
"Missing info section {key} in course {url}"
.
format
(
key
=
section_key
,
url
=
course
.
location
.
url
()))
...
...
lms/djangoapps/courseware/module_render.py
View file @
9b5285ad
...
...
@@ -143,8 +143,9 @@ def get_module(user, request, location, student_module_cache, course_id, positio
exists.
Arguments:
- user : current django User
- request : current django HTTPrequest
- user : User for whom we're getting the module
- request : current django HTTPrequest -- used in particular for auth
(This is important e.g. for prof impersonation of students in progress view)
- location : A Location-like object identifying the module to load
- student_module_cache : a StudentModuleCache
- course_id : the course_id in the context of which to load module
...
...
@@ -170,7 +171,9 @@ def _get_module(user, request, location, student_module_cache, course_id, positi
descriptor
=
modulestore
()
.
get_instance
(
course_id
,
location
)
# Short circuit--if the user shouldn't have access, bail without doing any work
if
not
has_access
(
user
,
descriptor
,
'load'
):
# NOTE: Do access check on request.user -- that's who actually needs access (e.g. could be prof
# impersonating a user)
if
not
has_access
(
request
.
user
,
descriptor
,
'load'
):
return
None
#TODO Only check the cache if this module can possibly have state
...
...
@@ -199,7 +202,10 @@ def _get_module(user, request, location, student_module_cache, course_id, positi
)
# Fully qualified callback URL for external queueing system
xqueue_callback_url
=
request
.
build_absolute_uri
(
'/'
)[:
-
1
]
# Trailing slash provided by reverse
xqueue_callback_url
=
'{proto}://{host}'
.
format
(
host
=
request
.
get_host
(),
proto
=
request
.
META
.
get
(
'HTTP_X_FORWARDED_PROTO'
,
'https'
if
request
.
is_secure
()
else
'http'
)
)
xqueue_callback_url
+=
reverse
(
'xqueue_callback'
,
kwargs
=
dict
(
course_id
=
course_id
,
userid
=
str
(
user
.
id
),
...
...
@@ -346,10 +352,10 @@ def xqueue_callback(request, course_id, userid, id, dispatch):
get
=
request
.
POST
.
copy
()
for
key
in
[
'xqueue_header'
,
'xqueue_body'
]:
if
not
get
.
has_key
(
key
):
r
eturn
Http404
r
aise
Http404
header
=
json
.
loads
(
get
[
'xqueue_header'
])
if
not
isinstance
(
header
,
dict
)
or
not
header
.
has_key
(
'lms_key'
):
r
eturn
Http404
r
aise
Http404
# Retrieve target StudentModule
user
=
User
.
objects
.
get
(
id
=
userid
)
...
...
lms/djangoapps/courseware/views.py
View file @
9b5285ad
...
...
@@ -325,14 +325,17 @@ def progress(request, course_id, student_id=None):
raise
Http404
student
=
User
.
objects
.
get
(
id
=
int
(
student_id
))
# NOTE: To make sure impersonation by instructor works, use
# student instead of request.user in the rest of the function.
student_module_cache
=
StudentModuleCache
.
cache_for_descriptor_descendents
(
course_id
,
request
.
user
,
course
)
course_module
=
get_module
(
request
.
user
,
request
,
course
.
location
,
course_id
,
student
,
course
)
course_module
=
get_module
(
student
,
request
,
course
.
location
,
student_module_cache
,
course_id
)
courseware_summary
=
grades
.
progress_summary
(
student
,
course_module
,
course
.
grader
,
student_module_cache
)
grade_summary
=
grades
.
grade
(
request
.
user
,
request
,
course
,
student_module_cache
)
grade_summary
=
grades
.
grade
(
student
,
request
,
course
,
student_module_cache
)
context
=
{
'course'
:
course
,
'courseware_summary'
:
courseware_summary
,
...
...
lms/djangoapps/django_comment_client/base/views.py
View file @
9b5285ad
...
...
@@ -51,11 +51,11 @@ def ajax_content_response(request, course_id, content, template_name):
'content'
:
content
,
}
html
=
render_to_string
(
template_name
,
context
)
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
safe_attributes
()
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
to_dict
()
annotated_content_info
=
utils
.
get_annotated_content_info
(
course_id
,
content
,
request
.
user
,
user_info
)
return
JsonResponse
({
'html'
:
html
,
'content'
:
content
,
'content'
:
utils
.
safe_content
(
content
)
,
'annotated_content_info'
:
annotated_content_info
,
})
...
...
@@ -78,7 +78,7 @@ def create_thread(request, course_id, commentable_id):
if
request
.
is_ajax
():
return
ajax_content_response
(
request
,
course_id
,
thread
.
to_dict
(),
'discussion/ajax_create_thread.html'
)
else
:
return
JsonResponse
(
thread
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
thread
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -90,7 +90,7 @@ def update_thread(request, course_id, thread_id):
if
request
.
is_ajax
():
return
ajax_content_response
(
request
,
course_id
,
thread
.
to_dict
(),
'discussion/ajax_update_thread.html'
)
else
:
return
JsonResponse
(
thread
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
thread
.
to_dict
()
))
def
_create_comment
(
request
,
course_id
,
thread_id
=
None
,
parent_id
=
None
):
post
=
request
.
POST
...
...
@@ -109,7 +109,7 @@ def _create_comment(request, course_id, thread_id=None, parent_id=None):
if
request
.
is_ajax
():
return
ajax_content_response
(
request
,
course_id
,
comment
.
to_dict
(),
'discussion/ajax_create_comment.html'
)
else
:
return
JsonResponse
(
comment
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
comment
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -126,7 +126,7 @@ def create_comment(request, course_id, thread_id):
def
delete_thread
(
request
,
course_id
,
thread_id
):
thread
=
cc
.
Thread
.
find
(
thread_id
)
thread
.
delete
()
return
JsonResponse
(
thread
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
thread
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -138,7 +138,7 @@ def update_comment(request, course_id, comment_id):
if
request
.
is_ajax
():
return
ajax_content_response
(
request
,
course_id
,
comment
.
to_dict
(),
'discussion/ajax_update_comment.html'
)
else
:
return
JsonResponse
(
comment
.
to_dict
()),
return
JsonResponse
(
utils
.
safe_content
(
comment
.
to_dict
()))
@require_POST
@login_required
...
...
@@ -147,7 +147,7 @@ def endorse_comment(request, course_id, comment_id):
comment
=
cc
.
Comment
.
find
(
comment_id
)
comment
.
endorsed
=
request
.
POST
.
get
(
'endorsed'
,
'false'
)
.
lower
()
==
'true'
comment
.
save
()
return
JsonResponse
(
comment
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
comment
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -156,7 +156,11 @@ def openclose_thread(request, course_id, thread_id):
thread
=
cc
.
Thread
.
find
(
thread_id
)
thread
.
closed
=
request
.
POST
.
get
(
'closed'
,
'false'
)
.
lower
()
==
'true'
thread
.
save
()
return
JsonResponse
(
thread
.
to_dict
())
thread
=
thread
.
to_dict
()
return
JsonResponse
({
'content'
:
utils
.
safe_content
(
thread
),
'ability'
:
utils
.
get_ability
(
course_id
,
thread
,
request
.
user
),
})
@require_POST
@login_required
...
...
@@ -173,7 +177,7 @@ def create_sub_comment(request, course_id, comment_id):
def
delete_comment
(
request
,
course_id
,
comment_id
):
comment
=
cc
.
Comment
.
find
(
comment_id
)
comment
.
delete
()
return
JsonResponse
(
comment
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
comment
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -182,7 +186,7 @@ def vote_for_comment(request, course_id, comment_id, value):
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
comment
=
cc
.
Comment
.
find
(
comment_id
)
user
.
vote
(
comment
,
value
)
return
JsonResponse
(
comment
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
comment
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -191,7 +195,7 @@ def undo_vote_for_comment(request, course_id, comment_id):
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
comment
=
cc
.
Comment
.
find
(
comment_id
)
user
.
unvote
(
comment
)
return
JsonResponse
(
comment
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
comment
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -200,7 +204,7 @@ def vote_for_thread(request, course_id, thread_id, value):
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
thread
=
cc
.
Thread
.
find
(
thread_id
)
user
.
vote
(
thread
,
value
)
return
JsonResponse
(
thread
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
thread
.
to_dict
()
))
@require_POST
@login_required
...
...
@@ -209,7 +213,7 @@ def undo_vote_for_thread(request, course_id, thread_id):
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
thread
=
cc
.
Thread
.
find
(
thread_id
)
user
.
unvote
(
thread
)
return
JsonResponse
(
thread
.
to_dict
(
))
return
JsonResponse
(
utils
.
safe_content
(
thread
.
to_dict
()
))
@require_POST
...
...
lms/djangoapps/django_comment_client/forum/views.py
View file @
9b5285ad
...
...
@@ -64,7 +64,7 @@ def render_discussion(request, course_id, threads, *args, **kwargs):
'user'
:
(
lambda
:
reverse
(
'django_comment_client.forum.views.user_profile'
,
args
=
[
course_id
,
user_id
])),
}[
discussion_type
]()
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
safe_attributes
()
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
to_dict
()
def
infogetter
(
thread
):
return
utils
.
get_annotated_content_infos
(
course_id
,
thread
,
request
.
user
,
user_info
)
...
...
@@ -83,7 +83,7 @@ def render_discussion(request, course_id, threads, *args, **kwargs):
'base_url'
:
base_url
,
'query_params'
:
strip_blank
(
strip_none
(
extract
(
query_params
,
[
'page'
,
'sort_key'
,
'sort_order'
,
'tags'
,
'text'
]))),
'annotated_content_info'
:
json
.
dumps
(
annotated_content_info
),
'discussion_data'
:
json
.
dumps
({
(
discussion_id
or
user_id
):
threads
})
'discussion_data'
:
json
.
dumps
({
(
discussion_id
or
user_id
):
map
(
utils
.
safe_content
,
threads
)
})
}
context
=
dict
(
context
.
items
()
+
query_params
.
items
())
return
render_to_string
(
template
,
context
)
...
...
@@ -128,7 +128,7 @@ def inline_discussion(request, course_id, discussion_id):
return
utils
.
JsonResponse
({
'html'
:
html
,
'discussion
Data'
:
threads
,
'discussion
_data'
:
map
(
utils
.
safe_content
,
threads
)
,
})
def
render_search_bar
(
request
,
course_id
,
discussion_id
=
None
,
text
=
''
):
...
...
@@ -149,7 +149,7 @@ def forum_form_discussion(request, course_id):
if
request
.
is_ajax
():
return
utils
.
JsonResponse
({
'html'
:
content
,
'discussion
Data'
:
threads
,
'discussion
_data'
:
map
(
utils
.
safe_content
,
threads
)
,
})
else
:
recent_active_threads
=
cc
.
search_recent_active_threads
(
...
...
@@ -176,7 +176,7 @@ def render_single_thread(request, discussion_id, course_id, thread_id):
thread
=
cc
.
Thread
.
find
(
thread_id
)
.
retrieve
(
recursive
=
True
)
.
to_dict
()
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
safe_attributes
()
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
to_dict
()
annotated_content_info
=
utils
.
get_annotated_content_infos
(
course_id
,
thread
=
thread
,
user
=
request
.
user
,
user_info
=
user_info
)
...
...
@@ -186,7 +186,7 @@ def render_single_thread(request, discussion_id, course_id, thread_id):
'annotated_content_info'
:
json
.
dumps
(
annotated_content_info
),
'course_id'
:
course_id
,
'request'
:
request
,
'discussion_data'
:
json
.
dumps
({
discussion_id
:
[
thread
]
}),
'discussion_data'
:
json
.
dumps
({
discussion_id
:
[
utils
.
safe_content
(
thread
)
]
}),
}
return
render_to_string
(
'discussion/_single_thread.html'
,
context
)
...
...
@@ -194,7 +194,7 @@ def single_thread(request, course_id, discussion_id, thread_id):
if
request
.
is_ajax
():
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
safe_attributes
()
user_info
=
cc
.
User
.
from_django_user
(
request
.
user
)
.
to_dict
()
thread
=
cc
.
Thread
.
find
(
thread_id
)
.
retrieve
(
recursive
=
True
)
annotated_content_info
=
utils
.
get_annotated_content_infos
(
course_id
,
thread
,
request
.
user
,
user_info
=
user_info
)
context
=
{
'thread'
:
thread
.
to_dict
(),
'course_id'
:
course_id
}
...
...
@@ -202,7 +202,7 @@ def single_thread(request, course_id, discussion_id, thread_id):
return
utils
.
JsonResponse
({
'html'
:
html
,
'content'
:
thread
.
to_dict
(
),
'content'
:
utils
.
safe_content
(
thread
.
to_dict
()
),
'annotated_content_info'
:
annotated_content_info
,
})
...
...
@@ -252,7 +252,7 @@ def user_profile(request, course_id, user_id):
if
request
.
is_ajax
():
return
utils
.
JsonResponse
({
'html'
:
content
,
'discussion
Data'
:
threads
,
'discussion
_data'
:
map
(
utils
.
safe_content
,
threads
)
,
})
else
:
context
=
{
...
...
lms/djangoapps/django_comment_client/utils.py
View file @
9b5285ad
...
...
@@ -164,6 +164,16 @@ class QueryCountDebugMiddleware(object):
logging
.
info
(
'
%
s queries run, total
%
s seconds'
%
(
len
(
connection
.
queries
),
total_time
))
return
response
def
get_ability
(
course_id
,
content
,
user
):
return
{
'editable'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"update_thread"
if
content
[
'type'
]
==
'thread'
else
"update_comment"
),
'can_reply'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"create_comment"
if
content
[
'type'
]
==
'thread'
else
"create_sub_comment"
),
'can_endorse'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"endorse_comment"
)
if
content
[
'type'
]
==
'comment'
else
False
,
'can_delete'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"delete_thread"
if
content
[
'type'
]
==
'thread'
else
"delete_comment"
),
'can_openclose'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"openclose_thread"
)
if
content
[
'type'
]
==
'thread'
else
False
,
'can_vote'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"vote_for_thread"
if
content
[
'type'
]
==
'thread'
else
"vote_for_comment"
),
}
def
get_annotated_content_info
(
course_id
,
content
,
user
,
user_info
):
voted
=
''
if
content
[
'id'
]
in
user_info
[
'upvoted_ids'
]:
...
...
@@ -173,14 +183,7 @@ def get_annotated_content_info(course_id, content, user, user_info):
return
{
'voted'
:
voted
,
'subscribed'
:
content
[
'id'
]
in
user_info
[
'subscribed_thread_ids'
],
'ability'
:
{
'editable'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"update_thread"
if
content
[
'type'
]
==
'thread'
else
"update_comment"
),
'can_reply'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"create_comment"
if
content
[
'type'
]
==
'thread'
else
"create_sub_comment"
),
'can_endorse'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"endorse_comment"
)
if
content
[
'type'
]
==
'comment'
else
False
,
'can_delete'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"delete_thread"
if
content
[
'type'
]
==
'thread'
else
"delete_comment"
),
'can_openclose'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"openclose_thread"
)
if
content
[
'type'
]
==
'thread'
else
False
,
'can_vote'
:
check_permissions_by_view
(
user
,
course_id
,
content
,
"vote_for_thread"
if
content
[
'type'
]
==
'thread'
else
"vote_for_comment"
),
},
'ability'
:
get_ability
(
course_id
,
content
,
user
),
}
def
get_annotated_content_infos
(
course_id
,
thread
,
user
,
user_info
):
...
...
@@ -216,3 +219,17 @@ def extend_content(content):
'permalink'
:
permalink
(
content
),
}
return
merge_dict
(
content
,
content_info
)
def
safe_content
(
content
):
fields
=
[
'id'
,
'title'
,
'body'
,
'course_id'
,
'anonymous'
,
'endorsed'
,
'parent_id'
,
'thread_id'
,
'votes'
,
'closed'
,
'created_at'
,
'updated_at'
,
'depth'
,
'type'
,
'commentable_id'
,
'comments_count'
,
'at_position_list'
,
'children'
,
'highlighted_title'
,
'highlighted_body'
,
]
if
content
.
get
(
'anonymous'
)
is
False
:
fields
+=
[
'username'
,
'user_id'
]
return
strip_none
(
extract
(
content
,
fields
))
lms/envs/aws.py
View file @
9b5285ad
...
...
@@ -23,9 +23,16 @@ DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
MITX_FEATURES
[
'ENABLE_DISCUSSION'
]
=
False
MITX_FEATURES
[
'ENABLE_DISCUSSION_SERVICE'
]
=
True
# IMPORTANT: With this enabled, the server must always be behind a proxy that
# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise,
# a user can fool our server into thinking it was an https connection.
# See https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
# for other warnings.
SECURE_PROXY_SSL_HEADER
=
(
'HTTP_X_FORWARDED_PROTO'
,
'https'
)
########################### NON-SECURE ENV CONFIG ##############################
# Things like server locations, ports, etc.
with
open
(
ENV_ROOT
/
"env.json"
)
as
env_file
:
ENV_TOKENS
=
json
.
load
(
env_file
)
...
...
@@ -49,6 +56,8 @@ LOGGING = get_logger_config(LOG_DIR,
COURSE_LISTINGS
=
ENV_TOKENS
.
get
(
'COURSE_LISTINGS'
,
{})
SUBDOMAIN_BRANDING
=
ENV_TOKENS
.
get
(
'SUBDOMAIN_BRANDING'
,
{})
COMMENTS_SERVICE_URL
=
ENV_TOKENS
.
get
(
"COMMENTS_SERVICE_URL"
,
''
)
COMMENTS_SERVICE_KEY
=
ENV_TOKENS
.
get
(
"COMMENTS_SERVICE_KEY"
,
''
)
############################## SECURE AUTH ITEMS ###############################
# Secret things: passwords, access keys, etc.
...
...
@@ -67,5 +76,3 @@ XQUEUE_INTERFACE = AUTH_TOKENS['XQUEUE_INTERFACE']
if
'COURSE_ID'
in
ENV_TOKENS
:
ASKBOT_URL
=
"courses/{0}/discussions/"
.
format
(
ENV_TOKENS
[
'COURSE_ID'
])
COMMENTS_SERVICE_URL
=
ENV_TOKENS
[
"COMMENTS_SERVICE_URL"
]
COMMENTS_SERVICE_KEY
=
ENV_TOKENS
[
"COMMENTS_SERVICE_KEY"
]
lms/envs/common.py
View file @
9b5285ad
...
...
@@ -332,6 +332,8 @@ WIKI_CAN_CHANGE_PERMISSIONS = lambda article, user: user.is_staff or user.is_sup
WIKI_CAN_ASSIGN
=
lambda
article
,
user
:
user
.
is_staff
or
user
.
is_superuser
WIKI_USE_BOOTSTRAP_SELECT_WIDGET
=
False
WIKI_LINK_LIVE_LOOKUPS
=
False
WIKI_LINK_DEFAULT_LEVEL
=
2
################################# Jasmine ###################################
JASMINE_TEST_DIRECTORY
=
PROJECT_ROOT
+
'/static/coffee'
...
...
lms/envs/dev_ike.py
View file @
9b5285ad
...
...
@@ -16,6 +16,8 @@ WIKI_ENABLED = False
MITX_FEATURES
[
'ENABLE_TEXTBOOK'
]
=
False
MITX_FEATURES
[
'ENABLE_DISCUSSION'
]
=
False
MITX_FEATURES
[
'ACCESS_REQUIRE_STAFF_FOR_COURSE'
]
=
True
# require that user be in the staff_* group to be able to enroll
MITX_FEATURES
[
'SUBDOMAIN_COURSE_LISTINGS'
]
=
False
MITX_FEATURES
[
'SUBDOMAIN_BRANDING'
]
=
False
MITX_FEATURES
[
'DISABLE_START_DATES'
]
=
True
# MITX_FEATURES['USE_DJANGO_PIPELINE']=False # don't recompile scss
...
...
lms/lib/comment_client/user.py
View file @
9b5285ad
...
...
@@ -33,16 +33,6 @@ class User(models.Model):
params
=
{
'source_type'
:
source
.
type
,
'source_id'
:
source
.
id
}
response
=
perform_request
(
'delete'
,
_url_for_subscription
(
self
.
id
),
params
)
# TODO this is a hack to compensate for the fact that synchronization isn't
# happening properly.
def
safe_attributes
(
self
):
try
:
return
self
.
to_dict
()
except
:
self
.
save
()
self
.
_retrieve
()
return
self
.
to_dict
()
def
vote
(
self
,
voteable
,
value
):
if
voteable
.
type
==
'thread'
:
url
=
_url_for_vote_thread
(
voteable
.
id
)
...
...
lms/static/coffee/src/discussion/content.coffee
View file @
9b5285ad
...
...
@@ -90,7 +90,9 @@ if Backbone?
ability
:
(
ability
)
->
for
action
,
elemSelector
of
@
model
.
actions
if
not
ability
[
action
]
@
$
(
elemSelector
).
parent
().
remove
()
@
$
(
elemSelector
).
parent
().
hide
()
else
@
$
(
elemSelector
).
parent
().
show
()
$discussionContent
:
->
@
_discussionContent
||=
@
$el
.
children
(
".discussion-content"
)
...
...
@@ -122,7 +124,7 @@ if Backbone?
url
=
@
model
.
urlFor
(
'retrieve'
)
DiscussionUtil
.
safeAjax
$elem
:
$elem
$loading
:
$
(
event
.
target
)
if
event
$loading
:
@
$
(
".discussion-show-comments"
)
type
:
"GET"
url
:
url
success
:
(
response
,
textStatus
)
=>
...
...
@@ -191,6 +193,8 @@ if Backbone?
comment
=
@
model
.
addComment
response
.
content
commentView
=
new
CommentView
el
:
$comment
[
0
],
model
:
comment
comment
.
updateInfo
response
.
annotated_content_info
if
autowatch
@
model
.
get
(
'thread'
).
set
(
'subscribed'
,
true
)
@
cancelReply
()
cancelReply
:
->
...
...
@@ -269,6 +273,7 @@ if Backbone?
data
:
data
success
:
(
response
,
textStatus
)
=>
@
model
.
set
(
'closed'
,
not
closed
)
@
model
.
set
(
'ability'
,
response
.
ability
)
edit
:
(
event
)
->
@
$
(
".discussion-content-wrapper"
).
hide
()
...
...
@@ -279,11 +284,11 @@ if Backbone?
view
=
{}
view
.
id
=
@
model
.
id
if
@
model
.
get
(
'type'
)
==
'thread'
view
.
title
=
@
$
(
".thread-raw-title"
).
html
(
)
view
.
body
=
@
$
(
".thread-raw-body"
).
html
(
)
view
.
tags
=
@
$
(
".thread-raw-tags"
).
html
(
)
view
.
title
=
@
model
.
get
(
'title'
)
view
.
body
=
@
model
.
get
(
'body'
)
view
.
tags
=
@
model
.
get
(
'tags'
)
else
view
.
body
=
@
$
(
".comment-raw-body"
).
html
(
)
view
.
body
=
@
model
.
get
(
'body'
)
@
$discussionContent
().
append
Mustache
.
render
DiscussionUtil
.
getTemplate
(
"_edit_
#{
@
model
.
get
(
'type'
)
}
"
),
view
DiscussionUtil
.
makeWmdEditor
@
$el
,
$
.
proxy
(
@
$
,
@
),
"
#{
@
model
.
get
(
'type'
)
}
-body-edit"
@
$
(
".thread-tags-edit"
).
tagsInput
DiscussionUtil
.
tagsInputOptions
()
...
...
@@ -311,8 +316,12 @@ if Backbone?
success
:
(
response
,
textStatus
)
=>
DiscussionUtil
.
clearFormErrors
@
$
(
".discussion-update-errors"
)
@
$discussionContent
().
replaceWith
(
response
.
html
)
@
model
.
set
response
.
content
@
model
.
updateInfo
response
.
annotated_content_info
if
@
model
.
get
(
'type'
)
==
'thread'
@
model
=
new
Thread
response
.
content
else
@
model
=
new
Comment
$
.
extend
{},
response
.
content
,
{
thread
:
@
model
.
get
(
'thread'
)
}
@
reconstruct
()
@
model
.
updateInfo
response
.
annotated_content_info
,
{
forceUpdate
:
true
}
cancelEdit
:
(
event
)
->
@
$
(
".discussion-content-edit"
).
hide
()
...
...
@@ -330,9 +339,11 @@ if Backbone?
DiscussionUtil
.
safeAjax
$elem
:
$elem
url
:
url
type
:
"POST"
success
:
(
response
,
textStatus
)
=>
@
$el
.
remove
()
@
model
.
get
(
'thread'
).
removeComment
(
@
model
)
if
@
model
.
get
(
'type'
)
==
'comment'
@
model
.
get
(
'thread'
).
removeComment
(
@
model
)
events
:
"click .discussion-follow-thread"
:
"toggleFollow"
...
...
@@ -381,6 +392,14 @@ if Backbone?
@
initTitle
()
@
initBody
()
@
initCommentViews
()
reconstruct
:
->
@
initBindings
()
@
initLocal
()
@
initTimeago
()
@
initTitle
()
@
initBody
()
@
delegateEvents
()
class
@
Thread
extends
@
Content
urlMappers
:
...
...
lms/static/coffee/src/discussion/discussion.coffee
View file @
9b5285ad
...
...
@@ -42,13 +42,17 @@ if Backbone?
DiscussionUtil
.
safeAjax
$elem
:
$elem
$loading
:
$elem
loadingCallback
:
->
$
(
this
).
parent
().
append
(
"<span class='discussion-loading'></span>"
)
loadedCallback
:
->
$
(
this
).
parent
().
children
(
".discussion-loading"
).
remove
()
url
:
url
type
:
"GET"
success
:
(
response
,
textStatus
)
=>
$parent
=
@
$el
.
parent
()
@
$el
.
replaceWith
(
response
.
html
)
$discussion
=
$parent
.
find
(
"section.discussion"
)
@
model
.
reset
(
response
.
discussion
D
ata
,
{
silent
:
false
})
@
model
.
reset
(
response
.
discussion
_d
ata
,
{
silent
:
false
})
view
=
new
DiscussionView
el
:
$discussion
[
0
],
model
:
@
model
DiscussionUtil
.
bulkUpdateContentInfo
(
window
.
$
$annotated_content_info
)
$
(
"html, body"
).
animate
({
scrollTop
:
0
},
0
)
...
...
@@ -109,6 +113,7 @@ if Backbone?
@
$
(
".discussion-cancel-post"
).
click
$
.
proxy
(
@
cancelNewPost
,
@
)
@
$el
.
children
(
".blank"
).
hide
()
@
$
(
".new-post-form"
).
show
()
submitNewPost
:
(
event
)
->
...
...
@@ -136,6 +141,8 @@ if Backbone?
$thread
=
$
(
response
.
html
)
@
$el
.
children
(
".threads"
).
prepend
(
$thread
)
@
$el
.
children
(
".blank"
).
remove
()
@
$
(
".new-post-similar-posts"
).
empty
()
@
$
(
".new-post-similar-posts-wrapper"
).
hide
()
@
$
(
".new-post-title"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
...
...
@@ -154,6 +161,7 @@ if Backbone?
@
$
(
".new-post-form"
).
addClass
(
"collapsed"
)
else
if
@
$el
.
hasClass
(
"forum-discussion"
)
@
$
(
".new-post-form"
).
hide
()
@
$el
.
children
(
".blank"
).
show
()
search
:
(
event
)
->
event
.
preventDefault
()
...
...
lms/static/coffee/src/discussion/discussion_module.coffee
View file @
9b5285ad
...
...
@@ -27,7 +27,7 @@ if Backbone?
$discussion
=
@
$el
.
find
(
"section.discussion"
)
$
(
event
.
target
).
html
(
"Hide Discussion"
)
discussion
=
new
Discussion
()
discussion
.
reset
(
response
.
discussion
D
ata
,
{
silent
:
false
})
discussion
.
reset
(
response
.
discussion
_d
ata
,
{
silent
:
false
})
view
=
new
DiscussionView
(
el
:
$discussion
[
0
],
model
:
discussion
)
DiscussionUtil
.
bulkUpdateContentInfo
(
window
.
$
$annotated_content_info
)
@
retrieved
=
true
...
...
lms/static/coffee/src/discussion/utils.coffee
View file @
9b5285ad
$
->
$
.
fn
.
extend
loading
:
->
$
(
this
).
after
(
"<span class='discussion-loading'></span>"
)
@
$_loading
=
$
(
"<span class='discussion-loading'></span>"
)
$
(
this
).
after
(
@
$_loading
)
loaded
:
->
$
(
this
).
parent
().
children
(
".discussion-loading"
)
.
remove
()
@
$_loading
.
remove
()
class
@
DiscussionUtil
...
...
@@ -72,13 +73,17 @@ class @DiscussionUtil
params
[
"beforeSend"
]
=
->
$elem
.
attr
(
"disabled"
,
"disabled"
)
if
params
[
"$loading"
]
console
.
log
"loading"
params
[
"$loading"
].
loading
()
if
params
[
"loadingCallback"
]
?
params
[
"loadingCallback"
].
apply
(
params
[
"$loading"
])
else
params
[
"$loading"
].
loading
()
$
.
ajax
(
params
).
always
->
$elem
.
removeAttr
(
"disabled"
)
if
params
[
"$loading"
]
console
.
log
"loaded"
params
[
"$loading"
].
loaded
()
if
params
[
"loadedCallback"
]
?
params
[
"loadedCallback"
].
apply
(
params
[
"$loading"
])
else
params
[
"$loading"
].
loaded
()
@
get
:
(
$elem
,
url
,
data
,
success
)
->
@
safeAjax
...
...
lms/static/coffee/src/navigation.coffee
View file @
9b5285ad
...
...
@@ -13,9 +13,10 @@ class @Navigation
active
:
active
header
:
'h3'
autoHeight
:
false
$
(
'#accordion .ui-state-active'
).
closest
(
'.chapter'
).
addClass
(
'is-open'
)
$
(
'#open_close_accordion a'
).
click
@
toggle
$
(
'#accordion'
).
show
()
$
(
'#accordion a'
).
click
@
setChapter
log
:
(
event
,
ui
)
->
log_event
'accordion'
,
...
...
@@ -24,3 +25,8 @@ class @Navigation
toggle
:
->
$
(
'.course-wrapper'
).
toggleClass
(
'closed'
)
setChapter
:
->
$
(
'#accordion .is-open'
).
removeClass
(
'is-open'
)
$
(
this
).
closest
(
'.chapter'
).
addClass
(
'is-open'
)
\ No newline at end of file
lms/static/js/jquery.gradebook.js
View file @
9b5285ad
...
...
@@ -4,13 +4,16 @@
var
Gradebook
=
function
(
$element
)
{
var
_this
=
this
;
var
$element
=
$element
;
var
$body
=
$
(
'body'
);
var
$grades
=
$element
.
find
(
'.grades'
);
var
$studentTable
=
$element
.
find
(
'.student-table'
);
var
$gradeTable
=
$element
.
find
(
'.grade-table'
);
var
$search
=
$element
.
find
(
'.student-search-field'
);
var
$leftShadow
=
$
(
'<div class="left-shadow"></div>'
);
var
$rightShadow
=
$
(
'<div class="right-shadow"></div>'
);
var
tableHeight
=
$gradeTable
.
height
();
var
maxScroll
=
$gradeTable
.
width
()
-
$grades
.
width
();
var
$body
=
$
(
'body'
);
var
mouseOrigin
;
var
tableOrigin
;
...
...
@@ -58,12 +61,35 @@ var Gradebook = function($element) {
var
targetLeft
=
clamp
(
$gradeTable
.
position
().
left
,
-
maxScroll
,
0
);
updateHorizontalPosition
(
targetLeft
);
setShadows
(
targetLeft
);
}
}
;
var
updateHorizontalPosition
=
function
(
left
)
{
$gradeTable
.
css
({
'left'
:
left
+
'px'
});
};
var
highlightRow
=
function
(
e
)
{
$element
.
find
(
'.highlight'
).
removeClass
(
'highlight'
);
var
index
=
$
(
this
).
index
();
$studentTable
.
find
(
'tr'
).
eq
(
index
+
1
).
addClass
(
'highlight'
);
$gradeTable
.
find
(
'tr'
).
eq
(
index
+
1
).
addClass
(
'highlight'
);
};
var
filter
=
function
(
e
)
{
var
term
=
$
(
this
).
val
();
if
(
term
.
length
>
0
)
{
$studentTable
.
find
(
'tbody tr'
).
hide
();
$gradeTable
.
find
(
'tbody tr'
).
hide
();
$studentTable
.
find
(
'tbody tr:contains('
+
term
+
')'
).
each
(
function
(
i
)
{
$
(
this
).
show
();
$gradeTable
.
find
(
'tr'
).
eq
(
$
(
this
).
index
()
+
1
).
show
();
});
}
else
{
$studentTable
.
find
(
'tbody tr'
).
show
();
$gradeTable
.
find
(
'tbody tr'
).
show
();
}
}
$leftShadow
.
css
(
'height'
,
tableHeight
+
'px'
);
...
...
@@ -72,5 +98,11 @@ var Gradebook = function($element) {
setShadows
(
0
);
$grades
.
css
(
'height'
,
tableHeight
);
$gradeTable
.
bind
(
'mousedown'
,
startDrag
);
$element
.
find
(
'tr'
).
bind
(
'mouseover'
,
highlightRow
);
$search
.
bind
(
'keyup'
,
filter
);
$
(
window
).
bind
(
'resize'
,
updateWidths
);
}
\ No newline at end of file
}
lms/static/js/jquery.sequence.js
View file @
9b5285ad
...
...
@@ -27,11 +27,6 @@ var SequenceNav = function($element) {
var
offset
=
e
.
pageX
-
mouseOrigin
;
var
targetLeft
=
clamp
(
listOrigin
+
offset
,
-
maxScroll
,
0
);
console
.
log
(
'---------------'
);
console
.
log
(
'offset: '
+
offset
);
console
.
log
(
'target left: '
+
targetLeft
);
console
.
log
(
'max: '
+
maxScroll
);
updateHorizontalPosition
(
targetLeft
);
setShadows
(
targetLeft
);
...
...
lms/static/sass/_discussion.scss
View file @
9b5285ad
...
...
@@ -150,10 +150,16 @@ $tag-text-color: #5b614f;
//user profile
.user-profile
{
@extend
.sidebar
;
margin-top
:
24px
;
}
.sidebar-username
{
font-size
:
1
.5em
;
font-weight
:
bold
;
line-height
:
1
.5em
;
margin-top
:
20px
;
}
.sidebar-user-roles
{
...
...
lms/static/sass/course/_gradebook.scss
View file @
9b5285ad
...
...
@@ -133,18 +133,6 @@ div.gradebook-wrapper {
box-shadow
:
0
1px
0
$table-border-color
inset
,
0
2px
0
rgba
(
255
,
255
,
255
,
.7
)
inset
;
border-left
:
1px
solid
#ccc
;
// &:before {
// content: '';
// display: block;
// position: absolute;
// left: 0;
// top: 0;
// z-index: 9999;
// width: 1px;
// height: 50px;
// @include linear-gradient(top, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, .15));
// }
&
:first-child
{
border-radius
:
5px
0
0
0
;
box-shadow
:
1px
1px
0
$table-border-color
inset
,
1px
2px
0
rgba
(
255
,
255
,
255
,
.7
)
inset
;
...
...
@@ -205,6 +193,19 @@ div.gradebook-wrapper {
@extend
.top-header
;
}
}
.student-table
tr
:hover
td
,
.grade-table
tr
:hover
td
,
.student-table
tr
.highlight
td
,
.grade-table
tr
.highlight
td
{
border-color
:
#74b7d6
;
@include
linear-gradient
(
#8ed6f7
,
#76cbf4
);
color
:
#333
;
a
{
color
:
#333
;
}
}
}
lms/static/sass/course/courseware/_courseware.scss
View file @
9b5285ad
...
...
@@ -13,6 +13,7 @@ div.course-wrapper {
section
.course-content
{
@extend
.content
;
padding
:
40px
;
line-height
:
1
.6
;
h1
{
margin
:
0
0
lh
();
...
...
lms/static/sass/course/courseware/_sidebar.scss
View file @
9b5285ad
...
...
@@ -75,6 +75,10 @@ section.course-index {
@include
box-shadow
(
0
1px
0
#fff
inset
,
0
-1px
0
rgba
(
0
,
0
,
0
,
.1
)
inset
);
@include
transition
(
background-color
.1s
);
&
.is-open
{
background
:
#fff
;
}
&
:first-child
{
border-radius
:
3px
0
0
0
;
}
...
...
lms/static/sass/course/layout/_courseware_header.scss
View file @
9b5285ad
...
...
@@ -67,7 +67,39 @@ header.global.slim {
@include
linear-gradient
(
top
,
#fff
,
#eee
);
.guest
.secondary
{
margin-right
:
0
;
}
.guest
.secondary
a
{
display
:
none
;
&
#login
{
display
:
block
;
@include
background-image
(
linear-gradient
(
-90deg
,
lighten
(
$blue
,
8%
)
,
lighten
(
$blue
,
5%
)
50%
,
$blue
50%
,
darken
(
$blue
,
10%
)
100%
));
border
:
1px
solid
transparent
;
border-color
:
darken
(
$blue
,
10%
);
@include
border-radius
(
3px
);
@include
box-sizing
(
border-box
);
@include
box-shadow
(
0
1px
0
0
rgba
(
255
,
255
,
255
,
0
.6
));
color
:
#fff
;
display
:
inline-block
;
font-family
:
$sans-serif
;
font-size
:
14px
;
font-weight
:
bold
;
@include
inline-block
;
letter-spacing
:
0
;
line-height
:
1em
;
margin
:
4px
;
padding
:
6px
12px
8px
;
text-decoration
:
none
;
text-transform
:
none
;
text-shadow
:
0
-1px
rgba
(
0
,
0
,
0
,
0
.6
);
vertical-align
:
middle
;
&
:hover
,
&
.active
{
@include
background-image
(
linear-gradient
(
-90deg
,
$blue
,
$blue
50%
,
$blue
50%
,
$blue
100%
));
}
}
}
nav
{
...
...
@@ -86,7 +118,7 @@ header.global.slim {
height
:
40px
;
position
:
absolute
;
right
:
3px
;
top
:
-8px
;
top
:
0
;
width
:
1px
;
}
...
...
@@ -97,7 +129,7 @@ header.global.slim {
height
:
40px
;
position
:
absolute
;
right
:
0px
;
top
:
-12px
;
top
:
0
;
width
:
1px
;
}
}
...
...
@@ -129,7 +161,7 @@ header.global.slim {
a
#signup
{
position
:
relative
;
margin-top
:
4
px
;
margin-top
:
3
px
;
padding
:
6px
12px
8px
;
text-transform
:
none
;
font-size
:
14px
;
...
...
lms/static/sass/course/wiki/_wiki.scss
View file @
9b5285ad
...
...
@@ -954,8 +954,7 @@ section.wiki {
.alert
{
position
:
relative
;
top
:
-15px
;
margin-bottom
:
24px
;
margin
:
24px
40px
;
padding
:
8px
12px
;
border
:
1px
solid
#EBE8BF
;
border-radius
:
3px
;
...
...
@@ -972,6 +971,10 @@ section.wiki {
}
}
.main-article
.alert
{
margin
:
0
0
24px
;
}
.missing
{
max-width
:
400px
;
margin
:
lh
(
2
)
auto
;
...
...
lms/static/sass/multicourse/_dashboard.scss
View file @
9b5285ad
...
...
@@ -68,8 +68,8 @@
@include
clearfix
;
border-bottom
:
1px
dotted
rgb
(
220
,
220
,
220
);
list-style
:
none
;
margin-bottom
:
20
px
;
padding-bottom
:
1
0
px
;
margin-bottom
:
15
px
;
padding-bottom
:
1
7
px
;
&
:hover
{
.title
.icon
{
...
...
@@ -77,16 +77,20 @@
}
}
span
{
display
:
block
;
}
span
.title
{
color
:
$lighter-base-font-color
;
float
:
left
;
font-family
:
$sans-serif
;
font-size
:
13px
;
.icon
{
background-size
:
cover
;
float
:
left
;
height
:
19px
;
margin
:
2px
8
px
0
0
;
margin
:
0
6
px
0
0
;
opacity
:
0
.6
;
@include
transition
(
all
,
0
.15s
,
linear
);
width
:
19px
;
...
...
@@ -112,7 +116,10 @@
span
.data
{
color
:
$lighter-base-font-color
;
font-weight
:
700
;
margin-left
:
12px
;
margin-left
:
26px
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
overflow
:
hidden
;
}
}
}
...
...
lms/templates/discussion/_content_renderer.html
View file @
9b5285ad
...
...
@@ -5,7 +5,7 @@
</
%
def>
<
%
def
name=
"render_content_with_comments(content, *args, **kwargs)"
>
<div
class=
"${content['type']
}${helpers.show_if(' endorsed', content.get('endorsed'))}"
_id=
"${content['id']}"
_discussion_id=
"${content.get('commentable_id', '')}"
_author_id=
"${helpers.show_if(content['user_id'], not content.get('anonymous'))
}"
>
<div
class=
"${content['type']
| h}${helpers.show_if(' endorsed', content.get('endorsed')) | h}"
_id=
"${content['id'] | h}"
_discussion_id=
"${content.get('commentable_id', '') | h}"
_author_id=
"${helpers.show_if(content['user_id'], not content.get('anonymous')) | h
}"
>
${render_content(content, *args, **kwargs)}
${render_comments(content.get('children', []), *args, **kwargs)}
</div>
...
...
lms/templates/discussion/_discussion_module.html
View file @
9b5285ad
<div
class=
"discussion-module"
>
<a
class=
"discussion-show control-button"
href=
"javascript:void(0)"
discussion_id=
"${discussion_id}"
>
Show Discussion
</a>
<a
class=
"discussion-show control-button"
href=
"javascript:void(0)"
discussion_id=
"${discussion_id
| h
}"
>
Show Discussion
</a>
</div>
lms/templates/discussion/_forum.html
View file @
9b5285ad
<
%
namespace
name=
"renderer"
file=
"_content_renderer.html"
/>
<section
class=
"discussion forum-discussion"
_id=
"${discussion_id}"
>
<section
class=
"discussion forum-discussion"
_id=
"${discussion_id
| h
}"
>
<div
class=
"discussion-non-content local"
>
<div
class=
"search-wrapper"
>
...
...
lms/templates/discussion/_inline.html
View file @
9b5285ad
<
%
namespace
name=
"renderer"
file=
"_content_renderer.html"
/>
<section
class=
"discussion inline-discussion"
_id=
"${discussion_id}"
>
<section
class=
"discussion inline-discussion"
_id=
"${discussion_id
| h
}"
>
<div
class=
"discussion-non-content local"
></div>
...
...
lms/templates/discussion/_paginator.html
View file @
9b5285ad
...
...
@@ -9,7 +9,7 @@
%
>
<
%
def
name=
"link_to_page(_page, text)"
>
<a
class=
"discussion-page-link"
href=
"javascript:void(0)"
page-url=
"${url_for_page(_page)}"
>
${text}
</a>
<a
class=
"discussion-page-link"
href=
"javascript:void(0)"
page-url=
"${url_for_page(_page)
| h
}"
>
${text}
</a>
</
%
def>
<
%
def
name=
"div_page(_page)"
>
...
...
@@ -36,7 +36,7 @@
% endfor
</
%
def>
<div
class=
"discussion-${discussion_type}-paginator discussion-paginator local"
>
<div
class=
"discussion-${discussion_type
| h
}-paginator discussion-paginator local"
>
<div
class=
"prev-page"
>
% if page > 1:
${link_to_page(page - 1, "
<
Previous page")}
...
...
lms/templates/discussion/_recent_active_posts.html
View file @
9b5285ad
...
...
@@ -8,7 +8,7 @@
</header>
<ol
class=
"discussion-sidebar-following-list"
>
% for thread in recent_active_threads:
<li><a
href=
"${helpers.permalink(thread)
}"
><span
class=
"sidebar-following-name"
>
${thread['title']}
</span>
<span
class=
"sidebar-vote-count"
>
${thread['votes']['point']
}
</span></a></li>
<li><a
href=
"${helpers.permalink(thread)
| h}"
><span
class=
"sidebar-following-name"
>
${thread['title'] | h}
</span>
<span
class=
"sidebar-vote-count"
>
${thread['votes']['point'] | h
}
</span></a></li>
% endfor
<ol>
</article>
...
...
lms/templates/discussion/_search_bar.html
View file @
9b5285ad
...
...
@@ -10,9 +10,9 @@ def base_url_for_search():
<form
action=
"${base_url_for_search()}"
method=
"get"
class=
"discussion-search-form"
>
% if query_params.get('tags', None):
<input
class=
"search-input"
type=
"text"
value=
"[${tags
}]${text
}"
id=
"keywords"
autocomplete=
"off"
/>
<input
class=
"search-input"
type=
"text"
value=
"[${tags
| h}]${text | h
}"
id=
"keywords"
autocomplete=
"off"
/>
% else:
<input
class=
"search-input"
type=
"text"
value=
"${text}"
id=
"keywords"
autocomplete=
"off"
/>
<input
class=
"search-input"
type=
"text"
value=
"${text
| h
}"
id=
"keywords"
autocomplete=
"off"
/>
% endif
<div
class=
"discussion-link discussion-search-link"
href=
"javascript:void(0)"
>
Search posts
</div>
</form>
lms/templates/discussion/_similar_posts.html
View file @
9b5285ad
...
...
@@ -3,7 +3,7 @@
<a
class=
"hide-similar-posts"
href=
"javascript:void(0)"
>
Hide
</a>
<div
class=
"new-post-similar-posts"
>
% for thread in threads:
<a
class=
"similar-post"
href=
"${thread['permalink']
}"
>
${thread['title']
}
</a>
<a
class=
"similar-post"
href=
"${thread['permalink']
| h}"
>
${thread['title'] | h
}
</a>
% endfor
</div>
% endif
lms/templates/discussion/_single_thread.html
View file @
9b5285ad
<
%
namespace
name=
"renderer"
file=
"_content_renderer.html"
/>
<section
class=
"discussion"
_id=
"${discussion_id}"
>
<section
class=
"discussion"
_id=
"${discussion_id
| h
}"
>
<a
class=
"discussion-title"
href=
"javascript:void(0)"
>
Discussion
</a>
<div
class=
"threads"
>
${renderer.render_content_with_comments(thread)}
...
...
lms/templates/discussion/_sort.html
View file @
9b5285ad
...
...
@@ -26,7 +26,7 @@
else:
return
base_url
+
'?'
+
urlencode
(
merge
(
query_params
,
{'
page
'
:
1
,
'
sort_key
'
:
key
,
'
sort_order
'
:
order
}))
%
>
<a
class=
"discussion-sort-link ${cls
}"
href=
"javascript:void(0)"
sort-url=
"${url_for_sort(key, order)
}"
>
${title}
</a>
<a
class=
"discussion-sort-link ${cls
| h}"
href=
"javascript:void(0)"
sort-url=
"${url_for_sort(key, order) | h
}"
>
${title}
</a>
</
%
def>
<div
class=
"discussion-sort local"
>
...
...
lms/templates/discussion/_trending_tags.html
View file @
9b5285ad
...
...
@@ -7,7 +7,7 @@
</header>
<ol
class=
"discussion-sidebar-tags-list"
>
% for tag, count in trending_tags:
<li><a
href=
"${helpers.url_for_tags(course.id, tag)
}"
class=
"thread-tag"
>
${tag}
</a><span
class=
"sidebar-tag-count"
>
×
${count
}
</span></li>
<li><a
href=
"${helpers.url_for_tags(course.id, tag)
| h}"
class=
"thread-tag"
>
${tag | h}
</a><span
class=
"sidebar-tag-count"
>
×
${count | h
}
</span></li>
% endfor
<ol>
</article>
...
...
lms/templates/discussion/_user_active_threads.html
View file @
9b5285ad
<
%
namespace
name=
"renderer"
file=
"_content_renderer.html"
/>
<section
class=
"discussion user-active-discussion"
_id=
"${user_id}"
>
<section
class=
"discussion user-active-discussion"
_id=
"${user_id
| h
}"
>
<div
class=
"discussion-non-content local"
></div>
...
...
lms/templates/discussion/_user_profile.html
View file @
9b5285ad
...
...
@@ -7,12 +7,12 @@
<
%
role_names =
sorted(map(attrgetter('name'),
django_user
.
roles
.
all
()))
%
>
<div
class=
"sidebar-username"
>
${django_user.username}
</div>
<div
class=
"sidebar-username"
>
${django_user.username
| h
}
</div>
<div
class=
"sidebar-user-roles"
>
${", ".join(role_names)}
</div>
<div
class=
"sidebar-threads-count"
><span>
${profiled_user['threads_count']
}
</span>
${pluralize('discussion', profiled_user['threads_count'])
} started
</div>
<div
class=
"sidebar-comments-count"
><span>
${profiled_user['comments_count']
}
</span>
${pluralize('comment', profiled_user['comments_count'])
}
</div>
<div
class=
"sidebar-threads-count"
><span>
${profiled_user['threads_count']
| h}
</span>
${pluralize('discussion', profiled_user['threads_count']) | h
} started
</div>
<div
class=
"sidebar-comments-count"
><span>
${profiled_user['comments_count']
| h}
</span>
${pluralize('comment', profiled_user['comments_count']) | h
}
</div>
% if check_permissions_by_view(user, course.id, content=None, name='update_moderator_status'):
% if "Moderator" in role_names:
<a
href=
"javascript:void(0)"
class=
"sidebar-toggle-moderator-button sidebar-revoke-moderator-button"
>
Revoke Moderator provileges
</a>
...
...
lms/templates/discussion/index.html
View file @
9b5285ad
<
%
inherit
file=
"../main.html"
/>
<
%
namespace
name=
'static'
file=
'../static_content.html'
/>
<
%
block
name=
"bodyclass"
>
discussion
</
%
block>
<
%
block
name=
"title"
><title>
Discussion – ${course.number}
</title></
%
block>
<
%
block
name=
"title"
><title>
Discussion – ${course.number
| h
}
</title></
%
block>
<
%
block
name=
"headextra"
>
<
%
static:css
group=
'course'
/>
...
...
lms/templates/discussion/mustache/_content.mustache
View file @
9b5285ad
...
...
@@ -7,28 +7,25 @@
</div>
<div
class=
"discussion-right-wrapper"
>
<ul
class=
"admin-actions"
>
<li><a
href=
"javascript:void(0)"
class=
"admin-endorse"
>
Endorse
</a></li>
<li><a
href=
"javascript:void(0)"
class=
"admin-edit"
>
Edit
</a></li>
<li><a
href=
"javascript:void(0)"
class=
"admin-delete"
>
Delete
</a></li>
<li
style=
"display: none;"
><a
href=
"javascript:void(0)"
class=
"admin-endorse"
>
Endorse
</a></li>
<li
style=
"display: none;"
><a
href=
"javascript:void(0)"
class=
"admin-edit"
>
Edit
</a></li>
<li
style=
"display: none;"
><a
href=
"javascript:void(0)"
class=
"admin-delete"
>
Delete
</a></li>
{{#
thread
}}
<li><a
href=
"javascript:void(0)"
class=
"admin-openclose"
>
{{
close_thread_text
}}
</a></li>
<li
style=
"display: none;"
><a
href=
"javascript:void(0)"
class=
"admin-openclose"
>
{{
close_thread_text
}}
</a></li>
{{/
thread
}}
</ul>
{{#
thread
}}
<a
class=
"thread-title"
name=
"
{{
content
.
id
}}
"
href=
"javascript:void(0)"
>
{{
content
.
displayed_title
}}
</a>
<div
class=
"thread-raw-title"
style=
"display: none"
>
{{{
content
.
title
}}}
</div>
{{/
thread
}}
<div
class=
"discussion-content-view"
>
<a
name=
"
{{
content
.
id
}}
"
style=
"width: 0; height: 0; padding: 0; border: none;"
></a>
<div
class=
"content-body
{{
content
.
type
}}
-body"
id=
"content-body-
{{
content
.
id
}}
"
>
{{
content
.
displayed_body
}}
</div>
<div
class=
"content-raw-body
{{
content
.
type
}}
-raw-body"
style=
"display: none"
>
{{{
content
.
body
}}}
</div>
{{#
thread
}}
<div
class=
"thread-tags"
>
{{#
content
.
tags
}}
<a
class=
"thread-tag"
href=
"
{{#
#
url_for_tags
}}{{
.
}}{{/
url_for_tags
}}
"
>
{{
.
}}
</a>
{{/
content
.
tags
}}
</div>
<div
class=
"thread-raw-tags"
style=
"display: none"
>
{{
content
.
raw_tags
}}
</div>
{{/
thread
}}
<div
class=
"info"
>
<div
class=
"comment-time"
>
...
...
lms/templates/discussion/user_profile.html
View file @
9b5285ad
...
...
@@ -3,7 +3,7 @@
<
%
inherit
file=
"../main.html"
/>
<
%
namespace
name=
'static'
file=
'../static_content.html'
/>
<
%
block
name=
"bodyclass"
>
discussion
</
%
block>
<
%
block
name=
"title"
><title>
Discussion – ${course.number}
</title></
%
block>
<
%
block
name=
"title"
><title>
Discussion – ${course.number
| h
}
</title></
%
block>
<
%
block
name=
"headextra"
>
<
%
static:css
group=
'course'
/>
...
...
@@ -36,6 +36,6 @@
</section>
<script
type=
"text/javascript"
>
var
$$profiled_user_id
=
"${user.id | escapejs}"
;
var
$$profiled_user_id
=
"${
django_
user.id | escapejs}"
;
var
$$course_id
=
"${course.id | escapejs}"
;
</script>
lms/templates/registration/password_reset_email.html
View file @
9b5285ad
...
...
@@ -3,7 +3,7 @@
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
https://
www.edx.org
{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
https://
{{domain}}
{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}
...
...
lms/templates/seq_module.html
View file @
9b5285ad
...
...
@@ -40,9 +40,6 @@
<script
type=
"text/javascript"
>
var
sequenceNav
;
$
(
document
).
ready
(
function
()
{
// console.log($('.sequence-nav'));
sequenceNav
=
new
SequenceNav
(
$
(
'.sequence-nav'
));
console
.
log
(
sequenceNav
);
});
</script>
lms/templates/wiki/article.html
View file @
9b5285ad
...
...
@@ -33,11 +33,9 @@
</div>
{% if urlpath %}
<!--
<div
class=
"see-children"
>
<a
href=
"{% url 'wiki:dir' path=urlpath.path %}"
>
See all children
</a>
</div>
-->
{% endif %}
</div>
</div>
...
...
lms/urls.py
View file @
9b5285ad
...
...
@@ -124,6 +124,8 @@ if settings.COURSEWARE_ENABLED:
'courseware.views.course_about'
,
name
=
"about_course"
),
#Inside the course
url
(
r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/$'
,
'courseware.views.course_info'
,
name
=
"course_root"
),
url
(
r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/info$'
,
'courseware.views.course_info'
,
name
=
"info"
),
url
(
r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/syllabus$'
,
...
...
@@ -197,7 +199,6 @@ if settings.QUICKEDIT:
if
settings
.
ASKBOT_ENABLED
:
urlpatterns
+=
(
url
(
r'^
%
s'
%
settings
.
ASKBOT_URL
,
include
(
'askbot.urls'
)),
\
url
(
r'^admin/'
,
include
(
admin
.
site
.
urls
)),
\
url
(
r'^settings/'
,
include
(
'askbot.deps.livesettings.urls'
)),
\
url
(
r'^followit/'
,
include
(
'followit.urls'
)),
\
# url(r'^robots.txt$', include('robots.urls')),
...
...
@@ -206,8 +207,10 @@ if settings.ASKBOT_ENABLED:
if
settings
.
DEBUG
:
## Jasmine
urlpatterns
=
urlpatterns
+
(
url
(
r'^_jasmine/'
,
include
(
'django_jasmine.urls'
)),)
## Jasmine and admin
urlpatterns
=
urlpatterns
+
(
url
(
r'^_jasmine/'
,
include
(
'django_jasmine.urls'
)),
url
(
r'^admin/'
,
include
(
admin
.
site
.
urls
)),
)
if
settings
.
MITX_FEATURES
.
get
(
'AUTH_USE_OPENID'
):
urlpatterns
+=
(
...
...
repo-requirements.txt
View file @
9b5285ad
-e git://github.com/MITx/django-staticfiles.git@6d2504e5c8#egg=django-staticfiles
-e git://github.com/MITx/django-pipeline.git#egg=django-pipeline
-e git://github.com/
benjaoming/django-wiki.git@533c7fc
#egg=django-wiki
-e git://github.com/
MITx/django-wiki.git@e2e84558
#egg=django-wiki
-e git://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev
-e common/lib/capa
-e common/lib/xmodule
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