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
9350a2c0
Commit
9350a2c0
authored
May 10, 2013
by
Steve Strassmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactoring views
parent
0bea50ed
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
351 additions
and
67 deletions
+351
-67
cms/djangoapps/contentstore/views/__init__.py
+12
-16
cms/djangoapps/contentstore/views/access.py
+1
-5
cms/djangoapps/contentstore/views/assets.py
+138
-2
cms/djangoapps/contentstore/views/checklist.py
+8
-1
cms/djangoapps/contentstore/views/component.py
+0
-0
cms/djangoapps/contentstore/views/course.py
+0
-0
cms/djangoapps/contentstore/views/error.py
+1
-1
cms/djangoapps/contentstore/views/item.py
+15
-1
cms/djangoapps/contentstore/views/preview.py
+15
-0
cms/djangoapps/contentstore/views/public.py
+5
-1
cms/djangoapps/contentstore/views/requests.py
+3
-38
cms/djangoapps/contentstore/views/session_kv_store.py
+1
-1
cms/djangoapps/contentstore/views/tabs.py
+110
-0
cms/djangoapps/contentstore/views/user.py
+42
-1
No files found.
cms/djangoapps/contentstore/views/__init__.py
View file @
9350a2c0
from
new
import
*
from
error
import
*
from
course
import
*
from
item
import
*
from
public
import
*
from
user
import
*
from
preview
import
*
from
assets
import
*
from
checklist
import
*
from
requests
import
landing
"""
# TODO: replace asterisks, should explicitly enumerate imports instead
from main import *
"""
from
assets
import
asset_index
,
upload_asset
,
import_course
,
generate_export_course
,
export_course
from
checklist
import
get_checklists
,
update_checklist
from
component
import
*
from
course
import
*
from
error
import
not_found
,
server_error
,
render_404
,
render_500
from
item
import
save_item
,
clone_item
,
delete_item
from
preview
import
preview_dispatch
,
preview_component
from
public
import
signup
,
old_login_redirect
,
login_page
,
howitworks
,
ux_alerts
from
user
import
index
,
add_user
,
remove_user
,
manage_users
from
tabs
import
edit_tabs
,
reorder_static_tabs
from
requests
import
edge
,
event
,
landing
cms/djangoapps/contentstore/views/access.py
View file @
9350a2c0
#from auth.authz import is_user_in_course_group_role, get_users_in_course_group_by_role
#from auth.authz import get_user_by_email, add_user_to_course_group, remove_user_from_course_group
#from auth.authz import INSTRUCTOR_ROLE_NAME, STAFF_ROLE_NAME, create_all_course_groups
from
auth.authz
import
STAFF_ROLE_NAME
,
INSTRUCTOR_ROLE_NAME
from
auth.authz
import
is_user_in_course_group_role
from
contentstore.utils
import
get_course_location_for_item
from
django.core.exceptions
import
PermissionDenied
def
get_location_and_verify_access
(
request
,
org
,
course
,
name
):
"""
...
...
cms/djangoapps/contentstore/views/assets.py
View file @
9350a2c0
import
logging
,
json
,
os
,
tarfile
,
shutil
from
tempfile
import
mkdtemp
from
path
import
path
from
django.conf
import
settings
from
django.http
import
HttpResponse
,
HttpResponseBadRequest
from
django.contrib.auth.decorators
import
login_required
from
django_future.csrf
import
ensure_csrf_cookie
from
django.core.urlresolvers
import
reverse
from
django.core.servers.basehttp
import
FileWrapper
from
django.core.files.temp
import
NamedTemporaryFile
from
mitxmako.shortcuts
import
render_to_response
from
cache_toolbox.core
import
del_cached_content
from
contentstore.utils
import
get_url_reverse
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.contentstore.django
import
contentstore
from
xmodule.modulestore.xml_exporter
import
export_to_xml
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore
import
Location
from
xmodule.contentstore.content
import
StaticContent
from
access
import
get_location_and_verify_access
from
xmodule.util.date_utils
import
get_default_time_display
from
mitxmako.shortcuts
import
render_to_response
from
access
import
get_location_and_verify_access
from
auth.authz
import
create_all_course_groups
@login_required
@ensure_csrf_cookie
...
...
@@ -116,3 +133,122 @@ def upload_asset(request, org, course, coursename):
response
[
'asset_url'
]
=
StaticContent
.
get_url_path_from_location
(
content
.
location
)
return
response
@ensure_csrf_cookie
@login_required
def
import_course
(
request
,
org
,
course
,
name
):
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
if
request
.
method
==
'POST'
:
filename
=
request
.
FILES
[
'course-data'
]
.
name
if
not
filename
.
endswith
(
'.tar.gz'
):
return
HttpResponse
(
json
.
dumps
({
'ErrMsg'
:
'We only support uploading a .tar.gz file.'
}))
data_root
=
path
(
settings
.
GITHUB_REPO_ROOT
)
course_subdir
=
"{0}-{1}-{2}"
.
format
(
org
,
course
,
name
)
course_dir
=
data_root
/
course_subdir
if
not
course_dir
.
isdir
():
os
.
mkdir
(
course_dir
)
temp_filepath
=
course_dir
/
filename
logging
.
debug
(
'importing course to {0}'
.
format
(
temp_filepath
))
# stream out the uploaded files in chunks to disk
temp_file
=
open
(
temp_filepath
,
'wb+'
)
for
chunk
in
request
.
FILES
[
'course-data'
]
.
chunks
():
temp_file
.
write
(
chunk
)
temp_file
.
close
()
tf
=
tarfile
.
open
(
temp_filepath
)
tf
.
extractall
(
course_dir
+
'/'
)
# find the 'course.xml' file
for
r
,
d
,
f
in
os
.
walk
(
course_dir
):
for
files
in
f
:
if
files
==
'course.xml'
:
break
if
files
==
'course.xml'
:
break
if
files
!=
'course.xml'
:
return
HttpResponse
(
json
.
dumps
({
'ErrMsg'
:
'Could not find the course.xml file in the package.'
}))
logging
.
debug
(
'found course.xml at {0}'
.
format
(
r
))
if
r
!=
course_dir
:
for
fname
in
os
.
listdir
(
r
):
shutil
.
move
(
r
/
fname
,
course_dir
)
module_store
,
course_items
=
import_from_xml
(
modulestore
(
'direct'
),
settings
.
GITHUB_REPO_ROOT
,
[
course_subdir
],
load_error_modules
=
False
,
static_content_store
=
contentstore
(),
target_location_namespace
=
Location
(
location
),
draft_store
=
modulestore
())
# we can blow this away when we're done importing.
shutil
.
rmtree
(
course_dir
)
logging
.
debug
(
'new course at {0}'
.
format
(
course_items
[
0
]
.
location
))
create_all_course_groups
(
request
.
user
,
course_items
[
0
]
.
location
)
return
HttpResponse
(
json
.
dumps
({
'Status'
:
'OK'
}))
else
:
course_module
=
modulestore
()
.
get_item
(
location
)
return
render_to_response
(
'import.html'
,
{
'context_course'
:
course_module
,
'active_tab'
:
'import'
,
'successful_import_redirect_url'
:
get_url_reverse
(
'CourseOutline'
,
course_module
)
})
@ensure_csrf_cookie
@login_required
def
generate_export_course
(
request
,
org
,
course
,
name
):
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
loc
=
Location
(
location
)
export_file
=
NamedTemporaryFile
(
prefix
=
name
+
'.'
,
suffix
=
".tar.gz"
)
root_dir
=
path
(
mkdtemp
())
# export out to a tempdir
logging
.
debug
(
'root = {0}'
.
format
(
root_dir
))
export_to_xml
(
modulestore
(
'direct'
),
contentstore
(),
loc
,
root_dir
,
name
,
modulestore
())
#filename = root_dir / name + '.tar.gz'
logging
.
debug
(
'tar file being generated at {0}'
.
format
(
export_file
.
name
))
tf
=
tarfile
.
open
(
name
=
export_file
.
name
,
mode
=
'w:gz'
)
tf
.
add
(
root_dir
/
name
,
arcname
=
name
)
tf
.
close
()
# remove temp dir
shutil
.
rmtree
(
root_dir
/
name
)
wrapper
=
FileWrapper
(
export_file
)
response
=
HttpResponse
(
wrapper
,
content_type
=
'application/x-tgz'
)
response
[
'Content-Disposition'
]
=
'attachment; filename=
%
s'
%
os
.
path
.
basename
(
export_file
.
name
)
response
[
'Content-Length'
]
=
os
.
path
.
getsize
(
export_file
.
name
)
return
response
@ensure_csrf_cookie
@login_required
def
export_course
(
request
,
org
,
course
,
name
):
location
=
get_location_and_verify_access
(
request
,
org
,
course
,
name
)
course_module
=
modulestore
()
.
get_item
(
location
)
return
render_to_response
(
'export.html'
,
{
'context_course'
:
course_module
,
'active_tab'
:
'export'
,
'successful_import_redirect_url'
:
''
})
cms/djangoapps/contentstore/views/checklist.py
View file @
9350a2c0
import
json
from
django.http
import
HttpResponse
,
HttpResponseBadRequest
from
django.contrib.auth.decorators
import
login_required
from
django_future.csrf
import
ensure_csrf_cookie
from
access
import
get_location_and_verify_access
from
mitxmako.shortcuts
import
render_to_response
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.inheritance
import
own_metadata
from
contentstore.utils
import
get_modulestore
,
get_url_reverse
from
requests
import
get_request_method
from
access
import
get_location_and_verify_access
@ensure_csrf_cookie
@login_required
...
...
cms/djangoapps/contentstore/views/component.py
0 → 100644
View file @
9350a2c0
This diff is collapsed.
Click to expand it.
cms/djangoapps/contentstore/views/course.py
View file @
9350a2c0
This diff is collapsed.
Click to expand it.
cms/djangoapps/contentstore/views/error.py
View file @
9350a2c0
from
django.http
import
HttpResponse
,
HttpResponse
ServerError
,
HttpResponseNotFound
from
django.http
import
HttpResponseServerError
,
HttpResponseNotFound
from
mitxmako.shortcuts
import
render_to_string
,
render_to_response
...
...
cms/djangoapps/contentstore/views/item.py
View file @
9350a2c0
import
json
from
uuid
import
uuid4
from
django.core.exceptions
import
PermissionDenied
from
django.http
import
HttpResponse
from
django.contrib.auth.decorators
import
login_required
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.inheritance
import
own_metadata
from
util.json_request
import
expect_json
from
mitxmako.shortcuts
import
render_to_response
from
contentstore.utils
import
get_modulestore
from
access
import
has_access
from
requests
import
_xmodule_recurse
# cdodge: these are categories which should not be parented, they are detached from the hierarchy
DETACHED_CATEGORIES
=
[
'about'
,
'static_tab'
,
'course_info'
]
@login_required
...
...
cms/djangoapps/contentstore/views/preview.py
View file @
9350a2c0
import
logging
,
sys
import
static_replace
from
xmodule_modifiers
import
replace_static_urls
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.errortracker
import
exc_info_to_str
from
django.core.urlresolvers
import
reverse
from
mitxmako.shortcuts
import
render_to_response
from
django.contrib.auth.decorators
import
login_required
from
xblock.runtime
import
DbModel
from
xmodule.x_module
import
ModuleSystem
...
...
@@ -6,6 +13,14 @@ from xmodule_modifiers import wrap_xmodule
from
session_kv_store
import
SessionKeyValueStore
from
requests
import
render_from_lms
from
functools
import
partial
from
xmodule.modulestore
import
Location
from
access
import
has_access
from
xmodule.modulestore.django
import
modulestore
from
xmodule.exceptions
import
NotFoundError
,
ProcessingError
from
django.http
import
HttpResponse
,
Http404
,
HttpResponseBadRequest
,
HttpResponseForbidden
log
=
logging
.
getLogger
(
__name__
)
@login_required
def
preview_dispatch
(
request
,
preview_id
,
location
,
dispatch
=
None
):
...
...
cms/djangoapps/contentstore/views/public.py
View file @
9350a2c0
from
external_auth.views
import
ssl_login_shortcut
from
mitxmako.shortcuts
import
render_to_response
from
django_future.csrf
import
ensure_csrf_cookie
from
requests
import
index
from
django.core.context_processors
import
csrf
from
django.shortcuts
import
redirect
from
django.conf
import
settings
from
user
import
index
"""
Public views
...
...
cms/djangoapps/contentstore/views/requests.py
View file @
9350a2c0
from
django.contrib.auth.decorators
import
login_required
from
django_future.csrf
import
ensure_csrf_cookie
from
mitxmako.shortcuts
import
render_to_response
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
access
import
has_access
from
contentstore.utils
import
get_url_reverse
,
get_lms_link_for_item
from
django.conf
import
settings
@login_required
@ensure_csrf_cookie
def
index
(
request
):
"""
List all courses available to the logged in user
"""
courses
=
modulestore
(
'direct'
)
.
get_items
([
'i4x'
,
None
,
None
,
'course'
,
None
])
# filter out courses that we don't have access too
def
course_filter
(
course
):
return
(
has_access
(
request
.
user
,
course
.
location
)
and
course
.
location
.
course
!=
'templates'
and
course
.
location
.
org
!=
''
and
course
.
location
.
course
!=
''
and
course
.
location
.
name
!=
''
)
courses
=
filter
(
course_filter
,
courses
)
return
render_to_response
(
'index.html'
,
{
'new_course_template'
:
Location
(
'i4x'
,
'edx'
,
'templates'
,
'course'
,
'Empty'
),
'courses'
:
[(
course
.
display_name
,
get_url_reverse
(
'CourseOutline'
,
course
),
get_lms_link_for_item
(
course
.
location
,
course_id
=
course
.
location
.
course_id
))
for
course
in
courses
],
'user'
:
request
.
user
,
'disable_course_creation'
:
settings
.
MITX_FEATURES
.
get
(
'DISABLE_COURSE_CREATION'
,
False
)
and
not
request
.
user
.
is_staff
})
# ==== Views with per-item permissions================================
import
json
from
django.http
import
HttpResponse
from
mitxmako.shortcuts
import
render_to_string
,
render_to_response
# points to the temporary course landing page with log in and sign up
def
landing
(
request
,
org
,
course
,
coursename
):
...
...
cms/djangoapps/contentstore/views/session_kv_store.py
View file @
9350a2c0
from
xblock.runtime
import
KeyValueStore
from
xblock.runtime
import
KeyValueStore
,
InvalidScopeError
class
SessionKeyValueStore
(
KeyValueStore
):
def
__init__
(
self
,
request
,
model_data
):
...
...
cms/djangoapps/contentstore/views/tabs.py
0 → 100644
View file @
9350a2c0
from
access
import
has_access
from
util.json_request
import
expect_json
from
django.http
import
HttpResponse
,
HttpResponseBadRequest
from
django.contrib.auth.decorators
import
login_required
from
django.core.exceptions
import
PermissionDenied
from
django_future.csrf
import
ensure_csrf_cookie
from
mitxmako.shortcuts
import
render_to_response
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.django
import
modulestore
from
contentstore.utils
import
get_course_for_item
def
initialize_course_tabs
(
course
):
# set up the default tabs
# I've added this because when we add static tabs, the LMS either expects a None for the tabs list or
# at least a list populated with the minimal times
# @TODO: I don't like the fact that the presentation tier is away of these data related constraints, let's find a better
# place for this. Also rather than using a simple list of dictionaries a nice class model would be helpful here
# This logic is repeated in xmodule/modulestore/tests/factories.py
# so if you change anything here, you need to also change it there.
course
.
tabs
=
[{
"type"
:
"courseware"
},
{
"type"
:
"course_info"
,
"name"
:
"Course Info"
},
{
"type"
:
"discussion"
,
"name"
:
"Discussion"
},
{
"type"
:
"wiki"
,
"name"
:
"Wiki"
},
{
"type"
:
"progress"
,
"name"
:
"Progress"
}]
modulestore
(
'direct'
)
.
update_metadata
(
course
.
location
.
url
(),
own_metadata
(
course
))
@login_required
@expect_json
def
reorder_static_tabs
(
request
):
tabs
=
request
.
POST
[
'tabs'
]
course
=
get_course_for_item
(
tabs
[
0
])
if
not
has_access
(
request
.
user
,
course
.
location
):
raise
PermissionDenied
()
# get list of existing static tabs in course
# make sure they are the same lengths (i.e. the number of passed in tabs equals the number
# that we know about) otherwise we can drop some!
existing_static_tabs
=
[
t
for
t
in
course
.
tabs
if
t
[
'type'
]
==
'static_tab'
]
if
len
(
existing_static_tabs
)
!=
len
(
tabs
):
return
HttpResponseBadRequest
()
# load all reference tabs, return BadRequest if we can't find any of them
tab_items
=
[]
for
tab
in
tabs
:
item
=
modulestore
(
'direct'
)
.
get_item
(
Location
(
tab
))
if
item
is
None
:
return
HttpResponseBadRequest
()
tab_items
.
append
(
item
)
# now just go through the existing course_tabs and re-order the static tabs
reordered_tabs
=
[]
static_tab_idx
=
0
for
tab
in
course
.
tabs
:
if
tab
[
'type'
]
==
'static_tab'
:
reordered_tabs
.
append
({
'type'
:
'static_tab'
,
'name'
:
tab_items
[
static_tab_idx
]
.
display_name
,
'url_slug'
:
tab_items
[
static_tab_idx
]
.
location
.
name
})
static_tab_idx
+=
1
else
:
reordered_tabs
.
append
(
tab
)
# OK, re-assemble the static tabs in the new order
course
.
tabs
=
reordered_tabs
modulestore
(
'direct'
)
.
update_metadata
(
course
.
location
,
own_metadata
(
course
))
return
HttpResponse
()
@login_required
@ensure_csrf_cookie
def
edit_tabs
(
request
,
org
,
course
,
coursename
):
location
=
[
'i4x'
,
org
,
course
,
'course'
,
coursename
]
course_item
=
modulestore
()
.
get_item
(
location
)
# check that logged in user has permissions to this item
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
# see tabs have been uninitialized (e.g. supporing courses created before tab support in studio)
if
course_item
.
tabs
is
None
or
len
(
course_item
.
tabs
)
==
0
:
initialize_course_tabs
(
course_item
)
# first get all static tabs from the tabs list
# we do this because this is also the order in which items are displayed in the LMS
static_tabs_refs
=
[
t
for
t
in
course_item
.
tabs
if
t
[
'type'
]
==
'static_tab'
]
static_tabs
=
[]
for
static_tab_ref
in
static_tabs_refs
:
static_tab_loc
=
Location
(
location
)
.
_replace
(
category
=
'static_tab'
,
name
=
static_tab_ref
[
'url_slug'
])
static_tabs
.
append
(
modulestore
(
'direct'
)
.
get_item
(
static_tab_loc
))
components
=
[
static_tab
.
location
.
url
()
for
static_tab
in
static_tabs
]
return
render_to_response
(
'edit-tabs.html'
,
{
'active_tab'
:
'pages'
,
'context_course'
:
course_item
,
'components'
:
components
})
cms/djangoapps/contentstore/views/user.py
View file @
9350a2c0
from
django.conf
import
settings
from
django.core.exceptions
import
PermissionDenied
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.decorators
import
login_required
from
django_future.csrf
import
ensure_csrf_cookie
from
util.json_request
import
expect_json
from
mitxmako.shortcuts
import
render_to_response
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
contentstore.utils
import
get_url_reverse
,
get_lms_link_for_item
from
access
import
has_access
from
requests
import
create_json_response
from
util.json_request
import
expect_json
from
auth.authz
import
STAFF_ROLE_NAME
,
INSTRUCTOR_ROLE_NAME
,
get_users_in_course_group_by_role
from
auth.authz
import
get_user_by_email
,
add_user_to_course_group
,
remove_user_from_course_group
def
user_author_string
(
user
):
'''Get an author string for commits by this user. Format:
first last <email@email.com>.
...
...
@@ -22,6 +36,33 @@ def user_author_string(user):
@login_required
@ensure_csrf_cookie
def
index
(
request
):
"""
List all courses available to the logged in user
"""
courses
=
modulestore
(
'direct'
)
.
get_items
([
'i4x'
,
None
,
None
,
'course'
,
None
])
# filter out courses that we don't have access too
def
course_filter
(
course
):
return
(
has_access
(
request
.
user
,
course
.
location
)
and
course
.
location
.
course
!=
'templates'
and
course
.
location
.
org
!=
''
and
course
.
location
.
course
!=
''
and
course
.
location
.
name
!=
''
)
courses
=
filter
(
course_filter
,
courses
)
return
render_to_response
(
'index.html'
,
{
'new_course_template'
:
Location
(
'i4x'
,
'edx'
,
'templates'
,
'course'
,
'Empty'
),
'courses'
:
[(
course
.
display_name
,
get_url_reverse
(
'CourseOutline'
,
course
),
get_lms_link_for_item
(
course
.
location
,
course_id
=
course
.
location
.
course_id
))
for
course
in
courses
],
'user'
:
request
.
user
,
'disable_course_creation'
:
settings
.
MITX_FEATURES
.
get
(
'DISABLE_COURSE_CREATION'
,
False
)
and
not
request
.
user
.
is_staff
})
@login_required
@ensure_csrf_cookie
def
manage_users
(
request
,
location
):
'''
This view will return all CMS users who are editors for the specified course
...
...
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