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):
return
UnitState
.
private
else
:
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
import
exceptions
import
json
...
...
@@ -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
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
.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
...
...
@@ -618,7 +619,7 @@ def upload_asset(request, org, course, coursename):
if
not
has_access
(
request
.
user
,
location
):
return
HttpResponseForbidden
()
# Does the course actually exist?!?
# Does the course actually exist?!?
Get anything from it to prove its existance
try
:
item
=
modulestore
()
.
get_item
(
location
)
...
...
@@ -635,23 +636,11 @@ def upload_asset(request, org, course, coursename):
mime_type
=
request
.
FILES
[
'file'
]
.
content_type
filedata
=
request
.
FILES
[
'file'
]
.
read
()
file_location
=
StaticContent
.
compute_location
(
org
,
course
,
name
)
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
)
thumbnail_file_location
=
None
# if we're uploading an image, then let's generate a thumbnail so that we can
# serve it up when needed without having to rescale on the fly
# if the upload asset is an image, we can generate a thumbnail from it
# 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'
:
try
:
# 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):
thumbnail_file
.
seek
(
0
)
# 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
thumbnail_file_location
=
StaticContent
.
compute_location
(
org
,
course
,
thumbnail_name
)
thumbnail_name
,
is_thumbnail
=
True
)
thumbnail_content
=
StaticContent
(
thumbnail_file_location
,
thumbnail_name
,
'image/jpeg'
,
thumbnail_file
)
contentstore
()
.
save
(
thumbnail_content
)
# remove any cached content at this location, as thumbnails are treated just like any
# other bit of static content
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
:
# catch, log, and continue as thumbnails are not a hard requirement
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
...
...
@@ -772,23 +782,69 @@ def remove_user(request, location):
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
def
landing
(
request
,
org
,
course
,
coursename
):
return
render_to_response
(
'temp-course-landing.html'
,
{})
def
static_pages
(
request
,
org
,
course
,
coursename
):
return
render_to_response
(
'static-pages.html'
,
{})
def
edit_static
(
request
,
org
,
course
,
coursename
):
return
render_to_response
(
'edit-static-page.html'
,
{})
def
not_found
(
request
):
return
render_to_response
(
'error.html'
,
{
'error'
:
'404'
})
def
server_error
(
request
):
return
render_to_response
(
'error.html'
,
{
'error'
:
'500'
})
\ No newline at end of file
return
render_to_response
(
'error.html'
,
{
'error'
:
'500'
})
@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() {
$modalCover
.
bind
(
'click'
,
hideHistoryModal
);
$
(
'.assets .upload-button'
).
bind
(
'click'
,
showUploadModal
);
$
(
'.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
);
$
(
'.new-unit-item'
).
bind
(
'click'
,
createNewUnit
);
$
(
'.save-subsection'
).
bind
(
'click'
,
saveSubsection
);
...
...
@@ -72,6 +76,17 @@ function removePolicyMetadata(e) {
_parent_el
.
remove
();
else
_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) {
function
startUpload
(
e
)
{
$
(
'.upload-modal h1'
).
html
(
'Uploading…'
);
$
(
'.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 .progress-bar'
).
removeClass
(
'loaded'
).
show
();
$
(
'.upload-modal .progress-fill'
).
html
(
''
).
css
(
'width'
,
'0'
).
animate
({
'width'
:
'100%'
},
1500
);
setTimeout
(
markAsLoaded
,
1500
);
}
function
resetUploadBar
(){
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
()
{
$
(
'.upload-modal .copy-button'
).
css
(
'display'
,
'inline-block'
);
$
(
'.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
)
{
e
.
preventDefault
();
...
...
cms/static/sass/_assets.scss
View file @
f0108757
...
...
@@ -86,6 +86,9 @@
}
}
}
.show-xml
{
@include
blue-button
;
}
}
.upload-modal
{
...
...
cms/templates/asset_index.html
View file @
f0108757
...
...
@@ -9,7 +9,8 @@
<div
class=
"inner-wrapper"
>
<h1>
Asset Library
</h1>
<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>
<article
class=
"asset-library"
>
<table>
...
...
@@ -22,149 +23,26 @@
</tr>
</thead>
<tbody>
% for asset in assets:
<tr>
<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
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
class=
"date-col"
>
10/2/2012
${asset['uploadDate']}
</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>
</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>
<a
class=
"show-xml"
href=
"${asset['url']}"
>
XML
</a>
</td>
</tr>
% endfor
</tbody>
</table>
<nav
class=
"pagination"
>
<nav
class=
"pagination
wip-box
"
>
Page:
<ol
class=
"pages"
>
<li>
1
</li>
...
...
@@ -187,14 +65,17 @@
<div
class=
"progress-bar"
>
<div
class=
"progress-fill"
></div>
</div>
<a
href=
"#"
class=
"copy-button"
>
Copy Embed Link
</a>
<div
class=
"file-chooser"
>
<div
class=
"embeddable-xml"
></div>
<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>
<input
type=
"file"
class=
"file-input"
>
</
div
>
<input
type=
"file"
class=
"file-input"
name=
"file"
>
</
form
>
</div>
</div>
<div
class=
"modal-cover"
></div>
</
%
block>
cms/templates/base.html
View file @
f0108757
...
...
@@ -33,6 +33,7 @@
<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.tablednd.js')}"
></script>
<script
src=
"http://malsup.github.com/jquery.form.js"
></script>
<script
type=
"text/javascript"
>
document
.
write
(
'
\
x3Cscript type="text/javascript" src="'
+
document
.
location
.
protocol
+
'//www.youtube.com/player_api">
\
x3C/script>'
);
...
...
cms/urls.py
View file @
f0108757
...
...
@@ -30,16 +30,17 @@ 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'^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'^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
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'^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
...
...
common/lib/xmodule/xmodule/contentstore/content.py
View file @
f0108757
XASSET_LOCATION_TAG
=
'c4x'
XASSET_SRCREF_PREFIX
=
'xasset:'
XASSET_THUMBNAIL_TAIL_NAME
=
'.
thumbnail.
jpg'
XASSET_THUMBNAIL_TAIL_NAME
=
'.jpg'
import
os
import
logging
from
xmodule.modulestore
import
Location
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
.
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
.
data
=
data
self
.
last_modified_at
=
last_modified_at
self
.
thumbnail_location
=
thumbnail_location
@property
def
is_thumbnail
(
self
):
return
self
.
name
.
endswith
(
XASSET_THUMBNAIL_TAIL_NAME
)
return
self
.
location
.
category
==
'thumbnail'
def
generate_thumbnail_name
(
self
):
return
(
'{0}'
+
XASSET_THUMBNAIL_TAIL_NAME
)
.
format
(
os
.
path
.
splitext
(
self
.
name
)[
0
])
@staticmethod
def
generate_thumbnail_name
(
original_name
):
return
(
'{0}'
+
XASSET_THUMBNAIL_TAIL_NAME
)
.
format
(
os
.
path
.
splitext
(
original_name
)[
0
])
@staticmethod
def
compute_location
(
org
,
course
,
name
,
revision
=
None
):
return
Location
([
XASSET_LOCATION_TAG
,
org
,
course
,
'asset'
,
name
,
revision
])
def
compute_location
(
org
,
course
,
name
,
revision
=
None
,
is_thumbnail
=
False
):
return
Location
([
XASSET_LOCATION_TAG
,
org
,
course
,
'asset'
if
not
is_thumbnail
else
'thumbnail'
,
Location
.
clean
(
name
)
,
revision
])
def
get_id
(
self
):
return
StaticContent
.
get_id_from_location
(
self
.
location
)
...
...
@@ -34,7 +36,10 @@ class StaticContent(object):
@staticmethod
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
def
get_id_from_location
(
location
):
...
...
@@ -65,4 +70,23 @@ class ContentStore(object):
raise
NotImplementedError
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
common/lib/xmodule/xmodule/contentstore/mongo.py
View file @
f0108757
...
...
@@ -28,7 +28,9 @@ class MongoContentStore(ContentStore):
if
self
.
fs
.
exists
({
"_id"
:
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
)
return
content
...
...
@@ -38,11 +40,18 @@ class MongoContentStore(ContentStore):
id
=
StaticContent
.
get_id_from_location
(
location
)
try
:
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
:
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:
...
...
@@ -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
items
=
self
.
fs_files
.
find
(
location_to_query
(
course_filter
))
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