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
f0108757
Commit
f0108757
authored
Oct 11, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #848 from MITx/feature/cas/lyla/asset-store-integration
Feature/cas/lyla/asset store integration
parents
6a7fb1d5
f06c67ef
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
200 additions
and
185 deletions
+200
-185
cms/djangoapps/contentstore/utils.py
+5
-0
cms/djangoapps/contentstore/views.py
+83
-28
cms/static/js/base.js
+42
-7
cms/static/sass/_assets.scss
+3
-0
cms/templates/asset_index.html
+17
-136
cms/templates/base.html
+1
-0
cms/urls.py
+3
-2
common/lib/xmodule/xmodule/contentstore/content.py
+32
-8
common/lib/xmodule/xmodule/contentstore/mongo.py
+14
-4
No files found.
cms/djangoapps/contentstore/utils.py
View file @
f0108757
...
@@ -74,3 +74,8 @@ def compute_unit_state(unit):
...
@@ -74,3 +74,8 @@ def compute_unit_state(unit):
return
UnitState
.
private
return
UnitState
.
private
else
:
else
:
return
UnitState
.
public
return
UnitState
.
public
def
get_date_display
(
date
):
print
date
,
type
(
date
)
return
date
.
strftime
(
"
%
d
%
B,
%
Y at
%
I:
%
M
%
p"
)
cms/djangoapps/contentstore/views.py
View file @
f0108757
import
traceback
from
util.json_request
import
expect_json
from
util.json_request
import
expect_json
import
exceptions
import
exceptions
import
json
import
json
...
@@ -44,7 +45,7 @@ from cache_toolbox.core import set_cached_content, get_cached_content, del_cache
...
@@ -44,7 +45,7 @@ from cache_toolbox.core import set_cached_content, get_cached_content, del_cache
from
auth.authz
import
is_user_in_course_group_role
,
get_users_in_course_group_by_role
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
get_user_by_email
,
add_user_to_course_group
,
remove_user_from_course_group
from
auth.authz
import
INSTRUCTOR_ROLE_NAME
,
STAFF_ROLE_NAME
from
auth.authz
import
INSTRUCTOR_ROLE_NAME
,
STAFF_ROLE_NAME
from
.utils
import
get_course_location_for_item
,
get_lms_link_for_item
,
compute_unit_state
from
.utils
import
get_course_location_for_item
,
get_lms_link_for_item
,
compute_unit_state
,
get_date_display
from
xmodule.templates
import
all_templates
from
xmodule.templates
import
all_templates
...
@@ -618,7 +619,7 @@ def upload_asset(request, org, course, coursename):
...
@@ -618,7 +619,7 @@ def upload_asset(request, org, course, coursename):
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
return
HttpResponseForbidden
()
return
HttpResponseForbidden
()
# Does the course actually exist?!?
# Does the course actually exist?!?
Get anything from it to prove its existance
try
:
try
:
item
=
modulestore
()
.
get_item
(
location
)
item
=
modulestore
()
.
get_item
(
location
)
...
@@ -635,23 +636,11 @@ def upload_asset(request, org, course, coursename):
...
@@ -635,23 +636,11 @@ def upload_asset(request, org, course, coursename):
mime_type
=
request
.
FILES
[
'file'
]
.
content_type
mime_type
=
request
.
FILES
[
'file'
]
.
content_type
filedata
=
request
.
FILES
[
'file'
]
.
read
()
filedata
=
request
.
FILES
[
'file'
]
.
read
()
file_location
=
StaticContent
.
compute_location
(
org
,
course
,
name
)
thumbnail_file_location
=
None
content
=
StaticContent
(
file_location
,
name
,
mime_type
,
filedata
)
# first commit to the DB
contentstore
()
.
save
(
content
)
# then remove the cache so we're not serving up stale content
# NOTE: we're not re-populating the cache here as the DB owns the last-modified timestamp
# which is used when serving up static content. This integrity is needed for
# browser-side caching support. We *could* re-fetch the saved content so that we have the
# timestamp populated, but we might as well wait for the first real request to come in
# to re-populate the cache.
del_cached_content
(
content
.
location
)
# if we're uploading an image, then let's generate a thumbnail so that we can
# if the upload asset is an image, we can generate a thumbnail from it
# serve it up when needed without having to rescale on the fly
# let's do so now, so that we have the thumbnail location which we need
# so that the asset can point to it
if
mime_type
.
split
(
'/'
)[
0
]
==
'image'
:
if
mime_type
.
split
(
'/'
)[
0
]
==
'image'
:
try
:
try
:
# not sure if this is necessary, but let's rewind the stream just in case
# not sure if this is necessary, but let's rewind the stream just in case
...
@@ -673,24 +662,45 @@ def upload_asset(request, org, course, coursename):
...
@@ -673,24 +662,45 @@ def upload_asset(request, org, course, coursename):
thumbnail_file
.
seek
(
0
)
thumbnail_file
.
seek
(
0
)
# use a naming convention to associate originals with the thumbnail
# use a naming convention to associate originals with the thumbnail
thumbnail_name
=
content
.
generate_thumbnail_name
(
)
thumbnail_name
=
StaticContent
.
generate_thumbnail_name
(
name
)
# then just store this thumbnail as any other piece of content
# then just store this thumbnail as any other piece of content
thumbnail_file_location
=
StaticContent
.
compute_location
(
org
,
course
,
thumbnail_file_location
=
StaticContent
.
compute_location
(
org
,
course
,
thumbnail_name
)
thumbnail_name
,
is_thumbnail
=
True
)
thumbnail_content
=
StaticContent
(
thumbnail_file_location
,
thumbnail_name
,
thumbnail_content
=
StaticContent
(
thumbnail_file_location
,
thumbnail_name
,
'image/jpeg'
,
thumbnail_file
)
'image/jpeg'
,
thumbnail_file
)
contentstore
()
.
save
(
thumbnail_content
)
contentstore
()
.
save
(
thumbnail_content
)
# remove any cached content at this location, as thumbnails are treated just like any
# remove any cached content at this location, as thumbnails are treated just like any
# other bit of static content
# other bit of static content
del_cached_content
(
thumbnail_content
.
location
)
del_cached_content
(
thumbnail_content
.
location
)
# not sure if this is necessary, but let's rewind the stream just in case
request
.
FILES
[
'file'
]
.
seek
(
0
)
except
:
except
:
# catch, log, and continue as thumbnails are not a hard requirement
# catch, log, and continue as thumbnails are not a hard requirement
logging
.
error
(
'Failed to generate thumbnail for {0}. Continuing...'
.
format
(
name
))
logging
.
error
(
'Failed to generate thumbnail for {0}. Continuing...'
.
format
(
name
))
thumbnail_file_location
=
None
file_location
=
StaticContent
.
compute_location
(
org
,
course
,
name
)
# create a StaticContent entity and point to the thumbnail
content
=
StaticContent
(
file_location
,
name
,
mime_type
,
filedata
,
thumbnail_location
=
thumbnail_file_location
)
return
HttpResponse
(
'Upload completed'
)
# first commit to the DB
contentstore
()
.
save
(
content
)
# then remove the cache so we're not serving up stale content
# NOTE: we're not re-populating the cache here as the DB owns the last-modified timestamp
# which is used when serving up static content. This integrity is needed for
# browser-side caching support. We *could* re-fetch the saved content so that we have the
# timestamp populated, but we might as well wait for the first real request to come in
# to re-populate the cache.
del_cached_content
(
content
.
location
)
response
=
HttpResponse
(
'Upload completed'
)
response
[
'asset_url'
]
=
StaticContent
.
get_url_path_from_location
(
file_location
)
return
response
'''
'''
This view will return all CMS users who are editors for the specified course
This view will return all CMS users who are editors for the specified course
...
@@ -772,23 +782,69 @@ def remove_user(request, location):
...
@@ -772,23 +782,69 @@ def remove_user(request, location):
return
create_json_response
()
return
create_json_response
()
@login_required
@ensure_csrf_cookie
def
asset_index
(
request
,
location
):
return
render_to_response
(
'asset_index.html'
,{})
# points to the temporary course landing page with log in and sign up
# points to the temporary course landing page with log in and sign up
def
landing
(
request
,
org
,
course
,
coursename
):
def
landing
(
request
,
org
,
course
,
coursename
):
return
render_to_response
(
'temp-course-landing.html'
,
{})
return
render_to_response
(
'temp-course-landing.html'
,
{})
def
static_pages
(
request
,
org
,
course
,
coursename
):
def
static_pages
(
request
,
org
,
course
,
coursename
):
return
render_to_response
(
'static-pages.html'
,
{})
return
render_to_response
(
'static-pages.html'
,
{})
def
edit_static
(
request
,
org
,
course
,
coursename
):
def
edit_static
(
request
,
org
,
course
,
coursename
):
return
render_to_response
(
'edit-static-page.html'
,
{})
return
render_to_response
(
'edit-static-page.html'
,
{})
def
not_found
(
request
):
def
not_found
(
request
):
return
render_to_response
(
'error.html'
,
{
'error'
:
'404'
})
return
render_to_response
(
'error.html'
,
{
'error'
:
'404'
})
def
server_error
(
request
):
def
server_error
(
request
):
return
render_to_response
(
'error.html'
,
{
'error'
:
'500'
})
return
render_to_response
(
'error.html'
,
{
'error'
:
'500'
})
\ No newline at end of file
@login_required
@ensure_csrf_cookie
def
asset_index
(
request
,
org
,
course
,
name
):
"""
Display an editable asset library
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
()
upload_asset_callback_url
=
reverse
(
'upload_asset'
,
kwargs
=
{
'org'
:
org
,
'course'
:
course
,
'coursename'
:
name
})
course_reference
=
StaticContent
.
compute_location
(
org
,
course
,
name
)
assets
=
contentstore
()
.
get_all_content_for_course
(
course_reference
)
thumbnails
=
contentstore
()
.
get_all_content_thumbnails_for_course
(
course_reference
)
asset_display
=
[]
for
asset
in
assets
:
id
=
asset
[
'_id'
]
display_info
=
{}
display_info
[
'displayname'
]
=
asset
[
'displayname'
]
display_info
[
'uploadDate'
]
=
get_date_display
(
asset
[
'uploadDate'
])
asset_location
=
StaticContent
.
compute_location
(
id
[
'org'
],
id
[
'course'
],
id
[
'name'
])
display_info
[
'url'
]
=
StaticContent
.
get_url_path_from_location
(
asset_location
)
# note, due to the schema change we may not have a 'thumbnail_location' in the result set
thumbnail_location
=
Location
(
asset
.
get
(
'thumbnail_location'
,
None
))
display_info
[
'thumb_url'
]
=
StaticContent
.
get_url_path_from_location
(
thumbnail_location
)
asset_display
.
append
(
display_info
)
return
render_to_response
(
'asset_index.html'
,
{
'assets'
:
asset_display
,
'upload_asset_callback_url'
:
upload_asset_callback_url
})
cms/static/js/base.js
View file @
f0108757
...
@@ -23,6 +23,10 @@ $(document).ready(function() {
...
@@ -23,6 +23,10 @@ $(document).ready(function() {
$modalCover
.
bind
(
'click'
,
hideHistoryModal
);
$modalCover
.
bind
(
'click'
,
hideHistoryModal
);
$
(
'.assets .upload-button'
).
bind
(
'click'
,
showUploadModal
);
$
(
'.assets .upload-button'
).
bind
(
'click'
,
showUploadModal
);
$
(
'.upload-modal .close-button'
).
bind
(
'click'
,
hideModal
);
$
(
'.upload-modal .close-button'
).
bind
(
'click'
,
hideModal
);
$
(
'a.show-xml'
).
toggle
(
showEmbeddableXML
,
hideEmbeddableXML
);
$
(
'a.copy-button'
).
toggle
(
showEmbeddableXML
,
hideEmbeddableXML
);
$
(
'.unit .item-actions .delete-button'
).
bind
(
'click'
,
deleteUnit
);
$
(
'.unit .item-actions .delete-button'
).
bind
(
'click'
,
deleteUnit
);
$
(
'.new-unit-item'
).
bind
(
'click'
,
createNewUnit
);
$
(
'.new-unit-item'
).
bind
(
'click'
,
createNewUnit
);
$
(
'.save-subsection'
).
bind
(
'click'
,
saveSubsection
);
$
(
'.save-subsection'
).
bind
(
'click'
,
saveSubsection
);
...
@@ -72,6 +76,17 @@ function removePolicyMetadata(e) {
...
@@ -72,6 +76,17 @@ function removePolicyMetadata(e) {
_parent_el
.
remove
();
_parent_el
.
remove
();
else
else
_parent_el
.
appendTo
(
"#policy-to-delete"
);
_parent_el
.
appendTo
(
"#policy-to-delete"
);
function
showEmbeddableXML
(
e
)
{
$ceiling
=
$
(
this
).
parents
(
'tr'
);
if
(
$ceiling
.
length
===
0
)
$ceiling
=
$
(
this
).
parents
(
'.upload-modal'
);
$ceiling
.
find
(
'.embeddable-xml'
).
html
(
'<img src="'
+
$
(
this
).
attr
(
'href'
)
+
'"/>'
);
}
function
hideEmbeddableXML
(
e
)
{
$ceiling
=
$
(
this
).
parents
(
'tr'
);
console
.
log
(
$ceiling
.
length
)
if
(
$ceiling
.
length
===
0
)
$ceiling
=
$
(
this
).
parents
(
'.upload-modal'
);
$ceiling
.
find
(
'.embeddable-xml'
).
html
(
""
);
}
}
...
@@ -233,20 +248,40 @@ function showFileSelectionMenu(e) {
...
@@ -233,20 +248,40 @@ function showFileSelectionMenu(e) {
function
startUpload
(
e
)
{
function
startUpload
(
e
)
{
$
(
'.upload-modal h1'
).
html
(
'Uploading…'
);
$
(
'.upload-modal h1'
).
html
(
'Uploading…'
);
$
(
'.upload-modal .file-name'
).
html
(
$
(
'.file-input'
).
val
());
$
(
'.upload-modal .file-name'
).
html
(
$
(
'.file-input'
).
val
());
$
(
'.upload-modal .file-chooser'
).
ajaxSubmit
({
beforeSend
:
resetUploadBar
,
uploadProgress
:
showUploadFeedback
,
complete
:
displayFinishedUpload
});
$
(
'.upload-modal .choose-file-button'
).
hide
();
$
(
'.upload-modal .choose-file-button'
).
hide
();
$
(
'.upload-modal .progress-bar'
).
removeClass
(
'loaded'
).
show
();
$
(
'.upload-modal .progress-bar'
).
removeClass
(
'loaded'
).
show
();
$
(
'.upload-modal .progress-fill'
).
html
(
''
).
css
(
'width'
,
'0'
).
animate
({
}
'width'
:
'100%'
},
1500
);
function
resetUploadBar
(){
setTimeout
(
markAsLoaded
,
1500
);
var
percentVal
=
'0%'
;
$
(
'.upload-modal .progress-fill'
).
width
(
percentVal
)
$
(
'.upload-modal .progress-fill'
).
html
(
percentVal
);
}
function
showUploadFeedback
(
event
,
position
,
total
,
percentComplete
)
{
var
percentVal
=
percentComplete
+
'%'
;
$
(
'.upload-modal .progress-fill'
).
width
(
percentVal
);
$
(
'.upload-modal .progress-fill'
).
html
(
percentVal
);
}
function
displayFinishedUpload
(
xhr
)
{
if
(
xhr
.
status
=
200
){
markAsLoaded
();
}
$
(
'.upload-modal .copy-button'
).
attr
(
'href'
,
xhr
.
getResponseHeader
(
'asset_url'
));
$
(
'.upload-modal .progress-fill'
).
html
(
xhr
.
responseText
);
$
(
'.upload-modal .choose-file-button'
).
html
(
'Load Another File'
).
show
();
}
}
function
markAsLoaded
()
{
function
markAsLoaded
()
{
$
(
'.upload-modal .copy-button'
).
css
(
'display'
,
'inline-block'
);
$
(
'.upload-modal .copy-button'
).
css
(
'display'
,
'inline-block'
);
$
(
'.upload-modal .progress-bar'
).
addClass
(
'loaded'
);
$
(
'.upload-modal .progress-bar'
).
addClass
(
'loaded'
);
$
(
'.upload-modal .progress-fill'
).
html
(
'loaded successfully'
);
}
$
(
'.upload-modal .choose-file-button'
).
html
(
'Load Another File'
).
show
();
}
function
hideModal
(
e
)
{
function
hideModal
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
...
...
cms/static/sass/_assets.scss
View file @
f0108757
...
@@ -86,6 +86,9 @@
...
@@ -86,6 +86,9 @@
}
}
}
}
}
}
.show-xml
{
@include
blue-button
;
}
}
}
.upload-modal
{
.upload-modal
{
...
...
cms/templates/asset_index.html
View file @
f0108757
...
@@ -9,7 +9,8 @@
...
@@ -9,7 +9,8 @@
<div
class=
"inner-wrapper"
>
<div
class=
"inner-wrapper"
>
<h1>
Asset Library
</h1>
<h1>
Asset Library
</h1>
<div
class=
"page-actions"
>
<div
class=
"page-actions"
>
<a
href=
"#"
class=
"upload-button"
>
Upload New File
</a><input
type=
"text"
class=
"asset-search-input search wip-box"
placeholder=
"search assets"
/>
<a
href=
"#"
class=
"upload-button"
>
Upload New File
</a>
<input
type=
"text"
class=
"asset-search-input search wip-box"
placeholder=
"search assets"
/>
</div>
</div>
<article
class=
"asset-library"
>
<article
class=
"asset-library"
>
<table>
<table>
...
@@ -22,149 +23,26 @@
...
@@ -22,149 +23,26 @@
</tr>
</tr>
</thead>
</thead>
<tbody>
<tbody>
% for asset in assets:
<tr>
<tr>
<td
class=
"thumb-col"
>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"
http://dribbble.s3.amazonaws.com/users/3185/screenshots/149571/picture_39.png
"
></div>
<div
class=
"thumb"
><img
src=
"
${asset['thumb_url']}
"
></div>
</td>
</td>
<td
class=
"name-col"
>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-1.jpg
</a>
<a
href=
"${asset['url']}"
class=
"filename"
>
${asset['displayname']}
</a>
<div
class=
"embeddable-xml"
></div>
</td>
</td>
<td
class=
"date-col"
>
<td
class=
"date-col"
>
10/2/2012
${asset['uploadDate']}
</td>
</td>
<td
class=
"embed-col"
>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
<a
class=
"show-xml"
href=
"${asset['url']}"
>
XML
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/4573/screenshots/157708/final.png"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-2.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/15101/screenshots/228625/star_wars_lightsbaer_2.jpg"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-2.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/3185/screenshots/149571/picture_39.png"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-1.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/4573/screenshots/157708/final.png"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-2.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/15101/screenshots/228625/star_wars_lightsbaer_2.jpg"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-2.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/3185/screenshots/149571/picture_39.png"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-1.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/4573/screenshots/157708/final.png"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-2.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/15101/screenshots/228625/star_wars_lightsbaer_2.jpg"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-2.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</tr>
<tr>
<td
class=
"thumb-col"
>
<div
class=
"thumb"
><img
src=
"http://dribbble.s3.amazonaws.com/users/3185/screenshots/149571/picture_39.png"
></div>
</td>
<td
class=
"name-col"
>
<a
href=
"#"
class=
"filename"
>
raygun-1.jpg
</a>
</td>
<td
class=
"date-col"
>
10/2/2012
</td>
<td
class=
"embed-col"
>
<a
href=
"#"
>
copy
</a>
</td>
</td>
</tr>
</tr>
% endfor
</tbody>
</tbody>
</table>
</table>
<nav
class=
"pagination"
>
<nav
class=
"pagination
wip-box
"
>
Page:
Page:
<ol
class=
"pages"
>
<ol
class=
"pages"
>
<li>
1
</li>
<li>
1
</li>
...
@@ -187,14 +65,17 @@
...
@@ -187,14 +65,17 @@
<div
class=
"progress-bar"
>
<div
class=
"progress-bar"
>
<div
class=
"progress-fill"
></div>
<div
class=
"progress-fill"
></div>
</div>
</div>
<a
href=
"#"
class=
"copy-button"
>
Copy Embed Link
</a>
<div
class=
"embeddable-xml"
></div>
<div
class=
"file-chooser"
>
<a
href=
"#"
class=
"copy-button"
>
Show Embeddable XML
</a>
<form
class=
"file-chooser"
action=
"${upload_asset_callback_url}"
method=
"post"
enctype=
"multipart/form-data"
>
<a
href=
"#"
class=
"choose-file-button"
>
Choose File
</a>
<a
href=
"#"
class=
"choose-file-button"
>
Choose File
</a>
<input
type=
"file"
class=
"file-input"
>
<input
type=
"file"
class=
"file-input"
name=
"file"
>
</
div
>
</
form
>
</div>
</div>
</div>
</div>
<div
class=
"modal-cover"
></div>
<div
class=
"modal-cover"
></div>
</
%
block>
</
%
block>
cms/templates/base.html
View file @
f0108757
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
<script
src=
"${static.url('js/vendor/jquery.cookie.js')}"
></script>
<script
src=
"${static.url('js/vendor/jquery.cookie.js')}"
></script>
<script
src=
"${static.url('js/vendor/jquery.leanModal.min.js')}"
></script>
<script
src=
"${static.url('js/vendor/jquery.leanModal.min.js')}"
></script>
<script
src=
"${static.url('js/vendor/jquery.tablednd.js')}"
></script>
<script
src=
"${static.url('js/vendor/jquery.tablednd.js')}"
></script>
<script
src=
"http://malsup.github.com/jquery.form.js"
></script>
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
document
.
write
(
'
\
x3Cscript type="text/javascript" src="'
+
document
.
write
(
'
\
x3Cscript type="text/javascript" src="'
+
document
.
location
.
protocol
+
'//www.youtube.com/player_api">
\
x3C/script>'
);
document
.
location
.
protocol
+
'//www.youtube.com/player_api">
\
x3C/script>'
);
...
...
cms/urls.py
View file @
f0108757
...
@@ -30,16 +30,17 @@ urlpatterns = ('',
...
@@ -30,16 +30,17 @@ urlpatterns = ('',
'contentstore.views.remove_user'
,
name
=
'remove_user'
),
'contentstore.views.remove_user'
,
name
=
'remove_user'
),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)/remove_user$'
,
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)/remove_user$'
,
'contentstore.views.remove_user'
,
name
=
'remove_user'
),
'contentstore.views.remove_user'
,
name
=
'remove_user'
),
url
(
r'^assets/(?P<location>.*?)$'
,
'contentstore.views.asset_index'
,
name
=
'asset_index'
),
url
(
r'^pages/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.static_pages'
,
name
=
'static_pages'
),
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_static/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.edit_static'
,
name
=
'edit_static'
),
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/assets/(?P<name>[^/]+)$'
,
'contentstore.views.asset_index'
,
name
=
'asset_index'
),
# temporary landing page for a course
# temporary landing page for a course
url
(
r'^landing/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.landing'
,
name
=
'landing'
),
url
(
r'^landing/(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<coursename>[^/]+)$'
,
'contentstore.views.landing'
,
name
=
'landing'
),
url
(
r'^not_found$'
,
'contentstore.views.not_found'
,
name
=
'not_found'
),
url
(
r'^not_found$'
,
'contentstore.views.not_found'
,
name
=
'not_found'
),
url
(
r'^server_error$'
,
'contentstore.views.server_error'
,
name
=
'server_error'
)
url
(
r'^server_error$'
,
'contentstore.views.server_error'
,
name
=
'server_error'
)
,
url
(
r'^(?P<org>[^/]+)/(?P<course>[^/]+)/assets/(?P<name>[^/]+)$'
,
'contentstore.views.asset_index'
,
name
=
'asset_index'
),
)
)
# User creation and updating views
# User creation and updating views
...
...
common/lib/xmodule/xmodule/contentstore/content.py
View file @
f0108757
XASSET_LOCATION_TAG
=
'c4x'
XASSET_LOCATION_TAG
=
'c4x'
XASSET_SRCREF_PREFIX
=
'xasset:'
XASSET_SRCREF_PREFIX
=
'xasset:'
XASSET_THUMBNAIL_TAIL_NAME
=
'.
thumbnail.
jpg'
XASSET_THUMBNAIL_TAIL_NAME
=
'.jpg'
import
os
import
os
import
logging
import
logging
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
class
StaticContent
(
object
):
class
StaticContent
(
object
):
def
__init__
(
self
,
loc
,
name
,
content_type
,
data
,
last_modified_at
=
None
):
def
__init__
(
self
,
loc
,
name
,
content_type
,
data
,
last_modified_at
=
None
,
thumbnail_location
=
None
):
self
.
location
=
loc
self
.
location
=
loc
self
.
name
=
name
#a display string which can be edited, and thus not part of the location which needs to be fixed
self
.
name
=
name
#a display string which can be edited, and thus not part of the location which needs to be fixed
self
.
content_type
=
content_type
self
.
content_type
=
content_type
self
.
data
=
data
self
.
data
=
data
self
.
last_modified_at
=
last_modified_at
self
.
last_modified_at
=
last_modified_at
self
.
thumbnail_location
=
thumbnail_location
@property
@property
def
is_thumbnail
(
self
):
def
is_thumbnail
(
self
):
return
self
.
name
.
endswith
(
XASSET_THUMBNAIL_TAIL_NAME
)
return
self
.
location
.
category
==
'thumbnail'
def
generate_thumbnail_name
(
self
):
@staticmethod
return
(
'{0}'
+
XASSET_THUMBNAIL_TAIL_NAME
)
.
format
(
os
.
path
.
splitext
(
self
.
name
)[
0
])
def
generate_thumbnail_name
(
original_name
):
return
(
'{0}'
+
XASSET_THUMBNAIL_TAIL_NAME
)
.
format
(
os
.
path
.
splitext
(
original_name
)[
0
])
@staticmethod
@staticmethod
def
compute_location
(
org
,
course
,
name
,
revision
=
None
):
def
compute_location
(
org
,
course
,
name
,
revision
=
None
,
is_thumbnail
=
False
):
return
Location
([
XASSET_LOCATION_TAG
,
org
,
course
,
'asset'
,
name
,
revision
])
return
Location
([
XASSET_LOCATION_TAG
,
org
,
course
,
'asset'
if
not
is_thumbnail
else
'thumbnail'
,
Location
.
clean
(
name
)
,
revision
])
def
get_id
(
self
):
def
get_id
(
self
):
return
StaticContent
.
get_id_from_location
(
self
.
location
)
return
StaticContent
.
get_id_from_location
(
self
.
location
)
...
@@ -34,7 +36,10 @@ class StaticContent(object):
...
@@ -34,7 +36,10 @@ class StaticContent(object):
@staticmethod
@staticmethod
def
get_url_path_from_location
(
location
):
def
get_url_path_from_location
(
location
):
return
"/{tag}/{org}/{course}/{category}/{name}"
.
format
(
**
location
.
dict
())
if
location
is
not
None
:
return
"/{tag}/{org}/{course}/{category}/{name}"
.
format
(
**
location
.
dict
())
else
:
return
None
@staticmethod
@staticmethod
def
get_id_from_location
(
location
):
def
get_id_from_location
(
location
):
...
@@ -65,4 +70,23 @@ class ContentStore(object):
...
@@ -65,4 +70,23 @@ class ContentStore(object):
raise
NotImplementedError
raise
NotImplementedError
def
get_all_content_for_course
(
self
,
location
):
def
get_all_content_for_course
(
self
,
location
):
'''
Returns a list of all static assets for a course. The return format is a list of dictionary elements. Example:
[
{u'displayname': u'profile.jpg', u'chunkSize': 262144, u'length': 85374,
u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 183000), u'contentType': u'image/jpeg',
u'_id': {u'category': u'asset', u'name': u'profile.jpg', u'course': u'6.002x', u'tag': u'c4x',
u'org': u'MITx', u'revision': None}, u'md5': u'36dc53519d4b735eb6beba51cd686a0e'},
{u'displayname': u'profile.thumbnail.jpg', u'chunkSize': 262144, u'length': 4073,
u'uploadDate': datetime.datetime(2012, 10, 3, 5, 41, 54, 196000), u'contentType': u'image/jpeg',
u'_id': {u'category': u'asset', u'name': u'profile.thumbnail.jpg', u'course': u'6.002x', u'tag': u'c4x',
u'org': u'MITx', u'revision': None}, u'md5': u'ff1532598830e3feac91c2449eaa60d6'},
....
]
'''
raise
NotImplementedError
raise
NotImplementedError
common/lib/xmodule/xmodule/contentstore/mongo.py
View file @
f0108757
...
@@ -28,7 +28,9 @@ class MongoContentStore(ContentStore):
...
@@ -28,7 +28,9 @@ class MongoContentStore(ContentStore):
if
self
.
fs
.
exists
({
"_id"
:
id
}):
if
self
.
fs
.
exists
({
"_id"
:
id
}):
self
.
fs
.
delete
(
id
)
self
.
fs
.
delete
(
id
)
with
self
.
fs
.
new_file
(
_id
=
id
,
filename
=
content
.
get_url_path
(),
content_type
=
content
.
content_type
,
displayname
=
content
.
name
)
as
fp
:
with
self
.
fs
.
new_file
(
_id
=
id
,
filename
=
content
.
get_url_path
(),
content_type
=
content
.
content_type
,
displayname
=
content
.
name
,
thumbnail_location
=
content
.
thumbnail_location
)
as
fp
:
fp
.
write
(
content
.
data
)
fp
.
write
(
content
.
data
)
return
content
return
content
...
@@ -38,11 +40,18 @@ class MongoContentStore(ContentStore):
...
@@ -38,11 +40,18 @@ class MongoContentStore(ContentStore):
id
=
StaticContent
.
get_id_from_location
(
location
)
id
=
StaticContent
.
get_id_from_location
(
location
)
try
:
try
:
with
self
.
fs
.
get
(
id
)
as
fp
:
with
self
.
fs
.
get
(
id
)
as
fp
:
return
StaticContent
(
location
,
fp
.
displayname
,
fp
.
content_type
,
fp
.
read
(),
fp
.
uploadDate
)
return
StaticContent
(
location
,
fp
.
displayname
,
fp
.
content_type
,
fp
.
read
(),
fp
.
uploadDate
,
thumbnail_location
=
fp
.
thumbnail_location
if
'thumbnail_location'
in
fp
else
None
)
except
NoFile
:
except
NoFile
:
raise
NotFoundError
()
raise
NotFoundError
()
def
get_all_content_info_for_course
(
self
,
location
):
def
get_all_content_thumbnails_for_course
(
self
,
location
):
return
self
.
_get_all_content_for_course
(
location
,
get_thumbnails
=
True
)
def
get_all_content_for_course
(
self
,
location
):
return
self
.
_get_all_content_for_course
(
location
,
get_thumbnails
=
False
)
def
_get_all_content_for_course
(
self
,
location
,
get_thumbnails
=
False
):
'''
'''
Returns a list of all static assets for a course. The return format is a list of dictionary elements. Example:
Returns a list of all static assets for a course. The return format is a list of dictionary elements. Example:
...
@@ -62,7 +71,8 @@ class MongoContentStore(ContentStore):
...
@@ -62,7 +71,8 @@ class MongoContentStore(ContentStore):
]
]
'''
'''
course_filter
=
Location
(
XASSET_LOCATION_TAG
,
category
=
"asset"
,
course
=
location
.
course
,
org
=
location
.
org
)
course_filter
=
Location
(
XASSET_LOCATION_TAG
,
category
=
"asset"
if
not
get_thumbnails
else
"thumbnail"
,
course
=
location
.
course
,
org
=
location
.
org
)
# 'borrow' the function 'location_to_query' from the Mongo modulestore implementation
# 'borrow' the function 'location_to_query' from the Mongo modulestore implementation
items
=
self
.
fs_files
.
find
(
location_to_query
(
course_filter
))
items
=
self
.
fs_files
.
find
(
location_to_query
(
course_filter
))
return
list
(
items
)
return
list
(
items
)
...
...
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