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
fbc48026
Commit
fbc48026
authored
Nov 08, 2012
by
Don Mitchell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Hopefully the course-info changes I had made w/o link destruction
parent
0fff578e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
191 additions
and
18 deletions
+191
-18
cms/djangoapps/contentstore/utils.py
+25
-0
cms/djangoapps/contentstore/views.py
+61
-17
cms/static/coffee/src/views/course_info_edit.coffee
+64
-0
cms/templates/course_info.html
+34
-0
cms/templates/widgets/header.html
+1
-0
cms/urls.py
+6
-1
No files found.
cms/djangoapps/contentstore/utils.py
View file @
fbc48026
...
...
@@ -33,6 +33,31 @@ def get_course_location_for_item(location):
return
location
def
get_course_for_item
(
location
):
'''
cdodge: for a given Xmodule, return the course that it belongs to
NOTE: This makes a lot of assumptions about the format of the course location
Also we have to assert that this module maps to only one course item - it'll throw an
assert if not
'''
item_loc
=
Location
(
location
)
# @hack! We need to find the course location however, we don't
# know the 'name' parameter in this context, so we have
# to assume there's only one item in this query even though we are not specifying a name
course_search_location
=
[
'i4x'
,
item_loc
.
org
,
item_loc
.
course
,
'course'
,
None
]
courses
=
modulestore
()
.
get_items
(
course_search_location
)
# make sure we found exactly one match on this above course search
found_cnt
=
len
(
courses
)
if
found_cnt
==
0
:
raise
BaseException
(
'Could not find course at {0}'
.
format
(
course_search_location
))
if
found_cnt
>
1
:
raise
BaseException
(
'Found more than one course at {0}. There should only be one!!! Dump = {1}'
.
format
(
course_search_location
,
courses
))
return
courses
[
0
]
def
get_lms_link_for_item
(
location
,
preview
=
False
):
location
=
Location
(
location
)
...
...
cms/djangoapps/contentstore/views.py
View file @
fbc48026
import
traceback
from
util.json_request
import
expect_json
import
exceptions
import
json
import
logging
import
mimetypes
import
os
import
StringIO
import
sys
import
time
import
tarfile
import
shutil
import
tempfile
from
datetime
import
datetime
from
collections
import
defaultdict
from
uuid
import
uuid4
from
lxml
import
etree
from
path
import
path
from
shutil
import
rmtree
# to install PIL on MacOSX: 'easy_install http://dist.repoze.org/PIL-1.1.6.tar.gz'
from
PIL
import
Image
...
...
@@ -28,8 +21,6 @@ from django.core.context_processors import csrf
from
django_future.csrf
import
ensure_csrf_cookie
from
django.core.urlresolvers
import
reverse
from
django.conf
import
settings
from
django
import
forms
from
django.shortcuts
import
redirect
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
...
...
@@ -43,23 +34,21 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from
xmodule.modulestore.django
import
modulestore
from
xmodule_modifiers
import
replace_static_urls
,
wrap_xmodule
from
xmodule.exceptions
import
NotFoundError
from
xmodule.timeparse
import
parse_time
,
stringify_time
from
functools
import
partial
from
itertools
import
groupby
from
operator
import
attrgetter
from
xmodule.contentstore.django
import
contentstore
from
xmodule.contentstore.content
import
StaticContent
from
cache_toolbox.core
import
set_cached_content
,
get_cached_content
,
del_cached_content
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
.utils
import
get_course_location_for_item
,
get_lms_link_for_item
,
compute_unit_state
,
get_date_display
,
UnitState
from
.utils
import
get_course_location_for_item
,
get_lms_link_for_item
,
compute_unit_state
,
get_date_display
,
UnitState
,
get_course_for_item
from
xmodule.templates
import
all_templates
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.modulestore.xml
import
edx_xml_parser
from
contentstore.course_info_model
import
get_course_updates
,
\
update_course_updates
,
delete_course_update
from
cache_toolbox.core
import
del_cached_content
from
xmodule.timeparse
import
stringify_time
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -346,7 +335,7 @@ def edit_unit(request, location):
def
preview_component
(
request
,
location
):
# TODO (vshnayder): change name from id to location in coffee+html as well.
if
not
has_access
(
request
.
user
,
location
):
raise
Http
404
# TODO (vshnayder): better error
raise
Http
ResponseForbidden
()
component
=
modulestore
()
.
get_item
(
location
)
...
...
@@ -908,6 +897,61 @@ def server_error(request):
@login_required
@ensure_csrf_cookie
def
course_info
(
request
,
org
,
course
,
name
,
provided_id
=
None
):
"""
Send models and views as well as html for editing the course info to the client.
org, course, name: Attributes of the Location for the item to edit
"""
location
=
[
'i4x'
,
org
,
course
,
'course'
,
name
]
# check that logged in user has permissions to this item
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
course_module
=
modulestore
()
.
get_item
(
location
)
# get current updates
location
=
[
'i4x'
,
org
,
course
,
'course_info'
,
"updates"
]
return
render_to_response
(
'course_info.html'
,
{
'active_tab'
:
'courseinfo-tab'
,
'context_course'
:
course_module
,
'url_base'
:
"/"
+
org
+
"/"
+
course
+
"/"
,
'course_updates'
:
json
.
dumps
(
get_course_updates
(
location
))
})
@expect_json
@login_required
@ensure_csrf_cookie
def
course_info_updates
(
request
,
org
,
course
,
provided_id
=
None
):
"""
restful CRUD operations on course_info updates.
org, course: Attributes of the Location for the item to edit
provided_id should be none if it's new (create) and a composite of the update db id + index otherwise.
"""
# ??? No way to check for access permission afaik
# get current updates
location
=
[
'i4x'
,
org
,
course
,
'course_info'
,
"updates"
]
# NB: we're setting Backbone.emulateHTTP to true on the client so everything comes as a post!!!
if
request
.
method
==
'POST'
and
'HTTP_X_HTTP_METHOD_OVERRIDE'
in
request
.
META
:
real_method
=
request
.
META
[
'HTTP_X_HTTP_METHOD_OVERRIDE'
]
else
:
real_method
=
request
.
method
if
request
.
method
==
'GET'
:
return
HttpResponse
(
json
.
dumps
(
get_course_updates
(
location
)),
mimetype
=
"application/json"
)
elif
real_method
==
'POST'
:
# new instance (unless django makes PUT a POST): updates are coming as POST. Not sure why.
return
HttpResponse
(
json
.
dumps
(
update_course_updates
(
location
,
request
.
POST
,
provided_id
)),
mimetype
=
"application/json"
)
elif
real_method
==
'PUT'
:
return
HttpResponse
(
json
.
dumps
(
update_course_updates
(
location
,
request
.
POST
,
provided_id
)),
mimetype
=
"application/json"
)
elif
real_method
==
'DELETE'
:
# coming as POST need to pull from Request Header X-HTTP-Method-Override DELETE
return
HttpResponse
(
json
.
dumps
(
delete_course_update
(
location
,
request
.
POST
,
provided_id
)),
mimetype
=
"application/json"
)
@login_required
@ensure_csrf_cookie
def
asset_index
(
request
,
org
,
course
,
name
):
"""
Display an editable asset library
...
...
cms/static/coffee/src/views/course_info_edit.coffee
0 → 100644
View file @
fbc48026
## Derived from and should inherit from a common ancestor w/ ModuleEdit
class
CMS
.
Views
.
CourseInfoEdit
extends
Backbone
.
View
tagName
:
'div'
className
:
'component'
events
:
"click .component-editor .cancel-button"
:
'clickCancelButton'
"click .component-editor .save-button"
:
'clickSaveButton'
"click .component-actions .edit-button"
:
'clickEditButton'
"click .component-actions .delete-button"
:
'onDelete'
initialize
:
->
@
render
()
$component_editor
:
=>
@
$el
.
find
(
'.component-editor'
)
loadDisplay
:
->
XModule
.
loadModule
(
@
$el
.
find
(
'.xmodule_display'
))
loadEdit
:
->
if
not
@
module
@
module
=
XModule
.
loadModule
(
@
$el
.
find
(
'.xmodule_edit'
))
# don't show metadata (deprecated for course_info)
render
:
->
if
@
model
.
id
@
$el
.
load
(
"/preview_component/
#{
@
model
.
id
}
"
,
=>
@
loadDisplay
()
@
delegateEvents
()
)
clickSaveButton
:
(
event
)
=>
event
.
preventDefault
()
data
=
@
module
.
save
()
@
model
.
save
(
data
).
done
(
=>
# # showToastMessage("Your changes have been saved.", null, 3)
@
module
=
null
@
render
()
@
$el
.
removeClass
(
'editing'
)
).
fail
(
->
showToastMessage
(
"There was an error saving your changes. Please try again."
,
null
,
3
)
)
clickCancelButton
:
(
event
)
->
event
.
preventDefault
()
@
$el
.
removeClass
(
'editing'
)
@
$component_editor
().
slideUp
(
150
)
clickEditButton
:
(
event
)
->
event
.
preventDefault
()
@
$el
.
addClass
(
'editing'
)
@
$component_editor
().
slideDown
(
150
)
@
loadEdit
()
onDelete
:
(
event
)
->
# clear contents, don't delete
@
model
.
definition
.
data
=
"<ol></ol>"
# TODO change label to 'clear'
onNew
:
(
event
)
->
ele
=
$
(
@
model
.
definition
.
data
).
find
(
"ol"
)
if
(
ele
)
ele
=
$
(
ele
).
first
().
prepend
(
"<li><h2>"
+
$
.
datepicker
.
formatDate
(
'MM d'
,
new
Date
())
+
"</h2>/n</li>"
);
\ No newline at end of file
cms/templates/course_info.html
0 → 100644
View file @
fbc48026
<
%
inherit
file=
"base.html"
/>
<!-- TODO decode course # from context_course into title -->
<
%
block
name=
"title"
>
Course Info
</
%
block>
<
%
block
name=
"jsextra"
>
<script
type=
"text/javascript"
charset=
"utf-8"
>
$
(
document
).
ready
(
function
(){
editor
=
new
CMS
.
Views
.
CourseInfoEdit
({
el
:
$
(
'.course-updates'
),
model
:
new
CMS
.
Models
.
Module
({
id
:
'${course_updates.location.url()}'
})
});
$
(
".new-update-button"
).
bind
(
'click'
,
editor
.
onNew
);
});
</script>
</
%
block>
<
%
block
name=
"content"
>
<div
class=
"main-wrapper"
>
<div
class=
"inner-wrapper"
>
<h1>
Course Info
</h1>
<div
class=
"main-column"
>
<div
class=
"window"
>
<h2>
Updates
</h2>
<a
href=
"#"
class=
"new-update-button"
>
New Update
</a>
<div
class=
"course-updates"
></div>
<!-- probably replace w/ a vertical where each element of the vertical is a separate update w/ a date and html field -->
</div>
</div>
<div
class=
"sidebar window"
>
</div>
</div>
</div>
</
%
block>
\ No newline at end of file
cms/templates/widgets/header.html
View file @
fbc48026
...
...
@@ -10,6 +10,7 @@
<a
href=
"${reverse('course_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}"
class=
"class-name"
>
${context_course.display_name}
</a>
<ul
class=
"class-nav"
>
<li><a
href=
"${reverse('course_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}"
id=
'courseware-tab'
>
Courseware
</a></li>
<li><a
href=
"${reverse('course_info', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}"
id=
'courseinfo-tab'
>
Course Info
</a></li>
<li><a
href=
"${reverse('edit_tabs', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, coursename=ctx_loc.name))}"
id=
'pages-tab'
>
Tabs
</a></li>
<li><a
href=
"${reverse('asset_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}"
id=
'assets-tab'
>
Assets
</a></li>
<li><a
href=
"${reverse('manage_users', kwargs=dict(location=ctx_loc))}"
id=
'users-tab'
>
Users
</a></li>
...
...
cms/urls.py
View file @
fbc48026
...
...
@@ -34,7 +34,12 @@ urlpatterns = ('',
'contentstore.views.remove_user'
,
name
=
'remove_user'
),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)/remove_user$'
,
'contentstore.views.remove_user'
,
name
=
'remove_user'
),
url
(
r'^pages/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.static_pages'
,
name
=
'static_pages'
),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/info/(?P<name>[^/]+)$'
,
'contentstore.views.course_info'
,
name
=
'course_info'
),
# ??? Is the following necessary or will the one below work w/ id=None if not sent?
# url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course_info/updates$', 'contentstore.views.course_info_updates', name='course_info'),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course_info/updates/(?P<provided_id>.*)$'
,
'contentstore.views.course_info_updates'
,
name
=
'course_info'
),
url
(
r'^pages/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.static_pages'
,
name
=
'static_pages'
),
url
(
r'^edit_static/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.edit_static'
,
name
=
'edit_static'
),
url
(
r'^edit_tabs/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.edit_tabs'
,
name
=
'edit_tabs'
),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/assets/(?P<name>[^/]+)$'
,
'contentstore.views.asset_index'
,
name
=
'asset_index'
),
...
...
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