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
5c433ec9
Commit
5c433ec9
authored
10 years ago
by
Sarina Canelake
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5731 from Stanford-Online/ataki/upstream
Limit Upload File Sizes to GridFS
parents
b1e5002b
fb9320af
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
244 additions
and
30 deletions
+244
-30
AUTHORS
+2
-2
cms/djangoapps/contentstore/views/assets.py
+31
-0
cms/djangoapps/contentstore/views/tests/test_assets.py
+31
-2
cms/envs/common.py
+10
-0
cms/static/coffee/spec/main.coffee
+9
-1
cms/static/coffee/spec/main_squire.coffee
+9
-1
cms/static/coffee/spec/views/assets_spec.coffee
+0
-0
cms/static/js/factories/asset_index.js
+9
-3
cms/static/js/spec/views/assets_spec.js
+51
-2
cms/static/js/views/assets.js
+68
-17
cms/static/js_test.yml
+4
-0
cms/static/js_test_squire.yml
+4
-0
cms/static/require-config.js
+9
-1
cms/templates/asset_index.html
+7
-1
No files found.
AUTHORS
View file @
5c433ec9
...
@@ -180,4 +180,5 @@ Eugeny Kolpakov <eugeny.kolpakov@gmail.com>
...
@@ -180,4 +180,5 @@ Eugeny Kolpakov <eugeny.kolpakov@gmail.com>
Omar Al-Ithawi <oithawi@qrf.org>
Omar Al-Ithawi <oithawi@qrf.org>
Louis Pilfold <louis@lpil.uk>
Louis Pilfold <louis@lpil.uk>
Akiva Leffert <akiva@edx.org>
Akiva Leffert <akiva@edx.org>
Mike Bifulco <mbifulco@aquent.com>
Mike Bifulco <mbifulco@aquent.com>
\ No newline at end of file
Jim Zheng <jimzheng@stanford.edu>
This diff is collapsed.
Click to expand it.
cms/djangoapps/contentstore/views/assets.py
View file @
5c433ec9
...
@@ -83,6 +83,9 @@ def _asset_index(request, course_key):
...
@@ -83,6 +83,9 @@ def _asset_index(request, course_key):
return
render_to_response
(
'asset_index.html'
,
{
return
render_to_response
(
'asset_index.html'
,
{
'context_course'
:
course_module
,
'context_course'
:
course_module
,
'max_file_size_in_mbs'
:
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
,
'chunk_size_in_mbs'
:
settings
.
UPLOAD_CHUNK_SIZE_IN_MB
,
'max_file_size_redirect_url'
:
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_URL
,
'asset_callback_url'
:
reverse_course_url
(
'assets_handler'
,
course_key
)
'asset_callback_url'
:
reverse_course_url
(
'assets_handler'
,
course_key
)
})
})
...
@@ -152,6 +155,14 @@ def _get_assets_for_page(request, course_key, current_page, page_size, sort):
...
@@ -152,6 +155,14 @@ def _get_assets_for_page(request, course_key, current_page, page_size, sort):
)
)
def
get_file_size
(
upload_file
):
"""
Helper method for getting file size of an upload file.
Can be used for mocking test file sizes.
"""
return
upload_file
.
size
@require_POST
@require_POST
@ensure_csrf_cookie
@ensure_csrf_cookie
@login_required
@login_required
...
@@ -176,6 +187,26 @@ def _upload_asset(request, course_key):
...
@@ -176,6 +187,26 @@ def _upload_asset(request, course_key):
upload_file
=
request
.
FILES
[
'file'
]
upload_file
=
request
.
FILES
[
'file'
]
filename
=
upload_file
.
name
filename
=
upload_file
.
name
mime_type
=
upload_file
.
content_type
mime_type
=
upload_file
.
content_type
size
=
get_file_size
(
upload_file
)
# If file is greater than a specified size, reject the upload
# request and send a message to the user. Note that since
# the front-end may batch large file uploads in smaller chunks,
# we validate the file-size on the front-end in addition to
# validating on the backend. (see cms/static/js/views/assets.js)
max_file_size_in_bytes
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
*
1000
**
2
if
size
>
max_file_size_in_bytes
:
return
JsonResponse
({
'error'
:
_
(
'File {filename} exceeds maximum size of '
'{size_mb} MB. Please follow the instructions here '
'to upload a file elsewhere and link to it instead: '
'{faq_url}'
)
.
format
(
filename
=
filename
,
size_mb
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
,
faq_url
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_URL
,
)
},
status
=
413
)
content_loc
=
StaticContent
.
compute_location
(
course_key
,
filename
)
content_loc
=
StaticContent
.
compute_location
(
course_key
,
filename
)
...
...
This diff is collapsed.
Click to expand it.
cms/djangoapps/contentstore/views/tests/test_assets.py
View file @
5c433ec9
...
@@ -5,6 +5,7 @@ from datetime import datetime
...
@@ -5,6 +5,7 @@ from datetime import datetime
from
io
import
BytesIO
from
io
import
BytesIO
from
pytz
import
UTC
from
pytz
import
UTC
import
json
import
json
from
django.conf
import
settings
from
contentstore.tests.utils
import
CourseTestCase
from
contentstore.tests.utils
import
CourseTestCase
from
contentstore.views
import
assets
from
contentstore.views
import
assets
from
contentstore.utils
import
reverse_course_url
from
contentstore.utils
import
reverse_course_url
...
@@ -16,10 +17,14 @@ from xmodule.modulestore.django import modulestore
...
@@ -16,10 +17,14 @@ from xmodule.modulestore.django import modulestore
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
xmodule.modulestore.xml_importer
import
import_from_xml
from
django.test.utils
import
override_settings
from
django.test.utils
import
override_settings
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
AssetLocation
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
,
AssetLocation
from
django.conf
import
settings
import
mock
from
ddt
import
ddt
from
ddt
import
data
TEST_DATA_DIR
=
settings
.
COMMON_TEST_DATA_ROOT
TEST_DATA_DIR
=
settings
.
COMMON_TEST_DATA_ROOT
MAX_FILE_SIZE
=
settings
.
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
*
1000
**
2
class
AssetsTestCase
(
CourseTestCase
):
class
AssetsTestCase
(
CourseTestCase
):
"""
"""
...
@@ -33,9 +38,14 @@ class AssetsTestCase(CourseTestCase):
...
@@ -33,9 +38,14 @@ class AssetsTestCase(CourseTestCase):
"""
"""
Post to the asset upload url
Post to the asset upload url
"""
"""
f
=
self
.
get_sample_asset
(
name
)
return
self
.
client
.
post
(
self
.
url
,
{
"name"
:
name
,
"file"
:
f
})
def
get_sample_asset
(
self
,
name
):
"""Returns an in-memory file with the given name for testing"""
f
=
BytesIO
(
name
)
f
=
BytesIO
(
name
)
f
.
name
=
name
+
".txt"
f
.
name
=
name
+
".txt"
return
self
.
client
.
post
(
self
.
url
,
{
"name"
:
name
,
"file"
:
f
})
return
f
class
BasicAssetsTestCase
(
AssetsTestCase
):
class
BasicAssetsTestCase
(
AssetsTestCase
):
...
@@ -132,6 +142,7 @@ class PaginationTestCase(AssetsTestCase):
...
@@ -132,6 +142,7 @@ class PaginationTestCase(AssetsTestCase):
self
.
assertGreaterEqual
(
name2
,
name3
)
self
.
assertGreaterEqual
(
name2
,
name3
)
@ddt
class
UploadTestCase
(
AssetsTestCase
):
class
UploadTestCase
(
AssetsTestCase
):
"""
"""
Unit tests for uploading a file
Unit tests for uploading a file
...
@@ -148,6 +159,24 @@ class UploadTestCase(AssetsTestCase):
...
@@ -148,6 +159,24 @@ class UploadTestCase(AssetsTestCase):
resp
=
self
.
client
.
post
(
self
.
url
,
{
"name"
:
"file.txt"
},
"application/json"
)
resp
=
self
.
client
.
post
(
self
.
url
,
{
"name"
:
"file.txt"
},
"application/json"
)
self
.
assertEquals
(
resp
.
status_code
,
400
)
self
.
assertEquals
(
resp
.
status_code
,
400
)
@data
(
(
int
(
MAX_FILE_SIZE
/
2.0
),
"small.file.test"
,
200
),
(
MAX_FILE_SIZE
,
"justequals.file.test"
,
200
),
(
MAX_FILE_SIZE
+
90
,
"large.file.test"
,
413
),
)
@mock.patch
(
'contentstore.views.assets.get_file_size'
)
def
test_file_size
(
self
,
case
,
get_file_size
):
max_file_size
,
name
,
status_code
=
case
get_file_size
.
return_value
=
max_file_size
f
=
self
.
get_sample_asset
(
name
=
name
)
resp
=
self
.
client
.
post
(
self
.
url
,
{
"name"
:
name
,
"file"
:
f
})
self
.
assertEquals
(
resp
.
status_code
,
status_code
)
class
DownloadTestCase
(
AssetsTestCase
):
class
DownloadTestCase
(
AssetsTestCase
):
"""
"""
...
...
This diff is collapsed.
Click to expand it.
cms/envs/common.py
View file @
5c433ec9
...
@@ -718,6 +718,16 @@ ADVANCED_SECURITY_CONFIG = {}
...
@@ -718,6 +718,16 @@ ADVANCED_SECURITY_CONFIG = {}
SHIBBOLETH_DOMAIN_PREFIX
=
'shib:'
SHIBBOLETH_DOMAIN_PREFIX
=
'shib:'
OPENID_DOMAIN_PREFIX
=
'openid:'
OPENID_DOMAIN_PREFIX
=
'openid:'
### Size of chunks into which asset uploads will be divided
UPLOAD_CHUNK_SIZE_IN_MB
=
10
### Max size of asset uploads to GridFS
MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
=
10
# FAQ url to direct users to if they upload
# a file that exceeds the above size
MAX_ASSET_UPLOAD_FILE_SIZE_URL
=
""
################ ADVANCED_COMPONENT_TYPES ###############
################ ADVANCED_COMPONENT_TYPES ###############
ADVANCED_COMPONENT_TYPES
=
[
ADVANCED_COMPONENT_TYPES
=
[
...
...
This diff is collapsed.
Click to expand it.
cms/static/coffee/spec/main.coffee
View file @
5c433ec9
...
@@ -15,6 +15,8 @@ requirejs.config({
...
@@ -15,6 +15,8 @@ requirejs.config({
"jquery.cookie"
:
"xmodule_js/common_static/js/vendor/jquery.cookie"
,
"jquery.cookie"
:
"xmodule_js/common_static/js/vendor/jquery.cookie"
,
"jquery.qtip"
:
"xmodule_js/common_static/js/vendor/jquery.qtip.min"
,
"jquery.qtip"
:
"xmodule_js/common_static/js/vendor/jquery.qtip.min"
,
"jquery.fileupload"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.fileupload"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.fileupload-process"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process"
,
"jquery.fileupload-validate"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate"
,
"jquery.iframe-transport"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.iframe-transport"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.inputnumber"
:
"xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.inputnumber"
:
"xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.immediateDescendents"
:
"xmodule_js/common_static/coffee/src/jquery.immediateDescendents"
,
"jquery.immediateDescendents"
:
"xmodule_js/common_static/coffee/src/jquery.immediateDescendents"
,
...
@@ -94,9 +96,15 @@ requirejs.config({
...
@@ -94,9 +96,15 @@ requirejs.config({
exports
:
"jQuery.fn.qtip"
exports
:
"jQuery.fn.qtip"
},
},
"jquery.fileupload"
:
{
"jquery.fileupload"
:
{
deps
:
[
"jquery.iframe-transport"
],
deps
:
[
"jquery.
ui"
,
"jquery.
iframe-transport"
],
exports
:
"jQuery.fn.fileupload"
exports
:
"jQuery.fn.fileupload"
},
},
"jquery.fileupload-process"
:
{
deps
:
[
"jquery.fileupload"
]
},
"jquery.fileupload-validate"
:
{
deps
:
[
"jquery.fileupload"
]
},
"jquery.inputnumber"
:
{
"jquery.inputnumber"
:
{
deps
:
[
"jquery"
],
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.inputNumber"
exports
:
"jQuery.fn.inputNumber"
...
...
This diff is collapsed.
Click to expand it.
cms/static/coffee/spec/main_squire.coffee
View file @
5c433ec9
...
@@ -14,6 +14,8 @@ requirejs.config({
...
@@ -14,6 +14,8 @@ requirejs.config({
"jquery.cookie"
:
"xmodule_js/common_static/js/vendor/jquery.cookie"
,
"jquery.cookie"
:
"xmodule_js/common_static/js/vendor/jquery.cookie"
,
"jquery.qtip"
:
"xmodule_js/common_static/js/vendor/jquery.qtip.min"
,
"jquery.qtip"
:
"xmodule_js/common_static/js/vendor/jquery.qtip.min"
,
"jquery.fileupload"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.fileupload"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.fileupload-process"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process"
,
"jquery.fileupload-validate"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate"
,
"jquery.iframe-transport"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.iframe-transport"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.inputnumber"
:
"xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.inputnumber"
:
"xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.immediateDescendents"
:
"xmodule_js/common_static/coffee/src/jquery.immediateDescendents"
,
"jquery.immediateDescendents"
:
"xmodule_js/common_static/coffee/src/jquery.immediateDescendents"
,
...
@@ -84,9 +86,15 @@ requirejs.config({
...
@@ -84,9 +86,15 @@ requirejs.config({
exports
:
"jQuery.fn.qtip"
exports
:
"jQuery.fn.qtip"
},
},
"jquery.fileupload"
:
{
"jquery.fileupload"
:
{
deps
:
[
"jquery.iframe-transport"
],
deps
:
[
"jquery.
ui"
,
"jquery.
iframe-transport"
],
exports
:
"jQuery.fn.fileupload"
exports
:
"jQuery.fn.fileupload"
},
},
"jquery.fileupload-process"
:
{
deps
:
[
"jquery.fileupload"
]
},
"jquery.fileupload-validate"
:
{
deps
:
[
"jquery.fileupload"
]
},
"jquery.inputnumber"
:
{
"jquery.inputnumber"
:
{
deps
:
[
"jquery"
],
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.inputNumber"
exports
:
"jQuery.fn.inputNumber"
...
...
This diff is collapsed.
Click to expand it.
cms/static/coffee/spec/views/assets_spec.coffee
View file @
5c433ec9
This diff is collapsed.
Click to expand it.
cms/static/js/factories/asset_index.js
View file @
5c433ec9
...
@@ -2,12 +2,18 @@ define([
...
@@ -2,12 +2,18 @@ define([
'jquery'
,
'js/collections/asset'
,
'js/views/assets'
,
'jquery.fileupload'
'jquery'
,
'js/collections/asset'
,
'js/views/assets'
,
'jquery.fileupload'
],
function
(
$
,
AssetCollection
,
AssetsView
)
{
],
function
(
$
,
AssetCollection
,
AssetsView
)
{
'use strict'
;
'use strict'
;
return
function
(
assetCallbackUrl
)
{
return
function
(
config
)
{
var
assets
=
new
AssetCollection
(),
var
assets
=
new
AssetCollection
(),
assetsView
;
assetsView
;
assets
.
url
=
assetCallbackUrl
;
assets
.
url
=
config
.
assetCallbackUrl
;
assetsView
=
new
AssetsView
({
collection
:
assets
,
el
:
$
(
'.assets-wrapper'
)});
assetsView
=
new
AssetsView
({
collection
:
assets
,
el
:
$
(
'.assets-wrapper'
),
uploadChunkSizeInMBs
:
config
.
uploadChunkSizeInMBs
,
maxFileSizeInMBs
:
config
.
maxFileSizeInMBs
,
maxFileSizeRedirectUrl
:
config
.
maxFileSizeRedirectUrl
});
assetsView
.
render
();
assetsView
.
render
();
};
};
});
});
This diff is collapsed.
Click to expand it.
cms/static/js/spec/views/assets_spec.js
View file @
5c433ec9
define
([
"jquery"
,
"js/common_helpers/ajax_helpers"
,
"js/views/asset"
,
"js/views/assets"
,
define
([
"jquery"
,
"js/common_helpers/ajax_helpers"
,
"js/views/asset"
,
"js/views/assets"
,
"js/models/asset"
,
"js/collections/asset"
,
"js/spec_helpers/view_helpers"
],
"js/models/asset"
,
"js/collections/asset"
,
"js/spec_helpers/view_helpers"
],
function
(
$
,
AjaxHelpers
,
AssetView
,
AssetsView
,
AssetModel
,
AssetCollection
,
ViewHelpers
)
{
function
(
$
,
AjaxHelpers
,
AssetView
,
AssetsView
,
AssetModel
,
AssetCollection
,
ViewHelpers
)
{
describe
(
"Assets"
,
function
()
{
describe
(
"Assets"
,
function
()
{
var
assetsView
,
mockEmptyAssetsResponse
,
mockAssetUploadResponse
,
var
assetsView
,
mockEmptyAssetsResponse
,
mockAssetUploadResponse
,
mockFileUpload
,
assetLibraryTpl
,
assetTpl
,
pagingFooterTpl
,
pagingHeaderTpl
,
uploadModalTpl
;
assetLibraryTpl
,
assetTpl
,
pagingFooterTpl
,
pagingHeaderTpl
,
uploadModalTpl
;
assetLibraryTpl
=
readFixtures
(
'asset-library.underscore'
);
assetLibraryTpl
=
readFixtures
(
'asset-library.underscore'
);
...
@@ -53,6 +53,10 @@ define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views
...
@@ -53,6 +53,10 @@ define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views
msg
:
"Upload completed"
msg
:
"Upload completed"
};
};
mockFileUpload
=
{
files
:
[{
name
:
'largefile'
,
size
:
0
}]
};
$
.
fn
.
fileupload
=
function
()
{
$
.
fn
.
fileupload
=
function
()
{
return
''
;
return
''
;
};
};
...
@@ -95,6 +99,15 @@ define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views
...
@@ -95,6 +99,15 @@ define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views
expect
(
$
(
'.upload-modal'
).
is
(
':visible'
)).
toBe
(
false
);
expect
(
$
(
'.upload-modal'
).
is
(
':visible'
)).
toBe
(
false
);
});
});
it
(
'has properly initialized constants for handling upload file errors'
,
function
()
{
expect
(
assetsView
).
toBeDefined
();
expect
(
assetsView
.
uploadChunkSizeInMBs
).
toBeDefined
();
expect
(
assetsView
.
maxFileSizeInMBs
).
toBeDefined
();
expect
(
assetsView
.
uploadChunkSizeInBytes
).
toBeDefined
();
expect
(
assetsView
.
maxFileSizeInBytes
).
toBeDefined
();
expect
(
assetsView
.
largeFileErrorMsg
).
toBeNull
();
});
it
(
'uploads file properly'
,
function
()
{
it
(
'uploads file properly'
,
function
()
{
var
requests
=
setup
.
call
(
this
);
var
requests
=
setup
.
call
(
this
);
expect
(
assetsView
).
toBeDefined
();
expect
(
assetsView
).
toBeDefined
();
...
@@ -122,6 +135,42 @@ define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views
...
@@ -122,6 +135,42 @@ define([ "jquery", "js/common_helpers/ajax_helpers", "js/views/asset", "js/views
expect
(
$
(
'#asset_table_body'
).
html
()).
toContain
(
"dummy.jpg"
);
expect
(
$
(
'#asset_table_body'
).
html
()).
toContain
(
"dummy.jpg"
);
expect
(
assetsView
.
collection
.
length
).
toBe
(
1
);
expect
(
assetsView
.
collection
.
length
).
toBe
(
1
);
});
});
it
(
'blocks file uploads larger than the max file size'
,
function
()
{
expect
(
assetsView
).
toBeDefined
();
mockFileUpload
.
files
[
0
].
size
=
assetsView
.
maxFileSize
*
10
;
$
(
'.choose-file-button'
).
click
();
$
(
".upload-modal .file-chooser"
).
fileupload
(
'add'
,
mockFileUpload
);
expect
(
$
(
'.upload-modal h1'
).
text
()).
not
.
toContain
(
"Uploading"
);
expect
(
assetsView
.
largeFileErrorMsg
).
toBeDefined
();
expect
(
$
(
'div.progress-bar'
).
text
()).
not
.
toContain
(
"Upload completed"
);
expect
(
$
(
'div.progress-fill'
).
width
()).
toBe
(
0
);
});
it
(
'allows file uploads equal in size to the max file size'
,
function
()
{
expect
(
assetsView
).
toBeDefined
();
mockFileUpload
.
files
[
0
].
size
=
assetsView
.
maxFileSize
;
$
(
'.choose-file-button'
).
click
();
$
(
".upload-modal .file-chooser"
).
fileupload
(
'add'
,
mockFileUpload
);
expect
(
assetsView
.
largeFileErrorMsg
).
toBeNull
();
});
it
(
'allows file uploads smaller than the max file size'
,
function
()
{
expect
(
assetsView
).
toBeDefined
();
mockFileUpload
.
files
[
0
].
size
=
assetsView
.
maxFileSize
/
100
;
$
(
'.choose-file-button'
).
click
();
$
(
".upload-modal .file-chooser"
).
fileupload
(
'add'
,
mockFileUpload
);
expect
(
assetsView
.
largeFileErrorMsg
).
toBeNull
();
});
});
});
});
});
});
});
This diff is collapsed.
Click to expand it.
cms/static/js/views/assets.js
View file @
5c433ec9
define
([
"jquery"
,
"underscore"
,
"gettext"
,
"js/models/asset"
,
"js/views/paging"
,
"js/views/asset"
,
define
([
"jquery"
,
"underscore"
,
"gettext"
,
"js/models/asset"
,
"js/views/paging"
,
"js/views/asset"
,
"js/views/paging_header"
,
"js/views/paging_footer"
,
"js/utils/modal"
,
"js/views/utils/view_utils"
],
"js/views/paging_header"
,
"js/views/paging_footer"
,
"js/utils/modal"
,
"js/views/utils/view_utils"
,
function
(
$
,
_
,
gettext
,
AssetModel
,
PagingView
,
AssetView
,
PagingHeader
,
PagingFooter
,
ModalUtils
,
ViewUtils
)
{
"js/views/feedback_notification"
,
"jquery.fileupload-process"
,
"jquery.fileupload-validate"
],
function
(
$
,
_
,
gettext
,
AssetModel
,
PagingView
,
AssetView
,
PagingHeader
,
PagingFooter
,
ModalUtils
,
ViewUtils
,
NotificationView
)
{
var
CONVERSION_FACTOR_MBS_TO_BYTES
=
1000
*
1000
;
var
AssetsView
=
PagingView
.
extend
({
var
AssetsView
=
PagingView
.
extend
({
// takes AssetCollection as model
// takes AssetCollection as model
...
@@ -10,7 +13,9 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -10,7 +13,9 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
"click .upload-button"
:
"showUploadModal"
"click .upload-button"
:
"showUploadModal"
},
},
initialize
:
function
()
{
initialize
:
function
(
options
)
{
options
=
options
||
{};
PagingView
.
prototype
.
initialize
.
call
(
this
);
PagingView
.
prototype
.
initialize
.
call
(
this
);
var
collection
=
this
.
collection
;
var
collection
=
this
.
collection
;
this
.
template
=
this
.
loadTemplate
(
"asset-library"
);
this
.
template
=
this
.
loadTemplate
(
"asset-library"
);
...
@@ -20,7 +25,16 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -20,7 +25,16 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
this
.
setInitialSortColumn
(
'js-asset-date-col'
);
this
.
setInitialSortColumn
(
'js-asset-date-col'
);
ViewUtils
.
showLoadingIndicator
();
ViewUtils
.
showLoadingIndicator
();
this
.
setPage
(
0
);
this
.
setPage
(
0
);
// set default file size for uploads via template var,
// and default to static old value if none exists
this
.
uploadChunkSizeInMBs
=
options
.
uploadChunkSizeInMBs
||
10
;
this
.
maxFileSizeInMBs
=
options
.
maxFileSizeInMBs
||
10
;
this
.
uploadChunkSizeInBytes
=
this
.
uploadChunkSizeInMBs
*
CONVERSION_FACTOR_MBS_TO_BYTES
;
this
.
maxFileSizeInBytes
=
this
.
maxFileSizeInMBs
*
CONVERSION_FACTOR_MBS_TO_BYTES
;
this
.
maxFileSizeRedirectUrl
=
options
.
maxFileSizeRedirectUrl
||
''
;
assetsView
=
this
;
assetsView
=
this
;
// error message modal for large file uploads
this
.
largeFileErrorMsg
=
null
;
},
},
render
:
function
()
{
render
:
function
()
{
...
@@ -111,6 +125,9 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -111,6 +125,9 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
}
}
$
(
'.file-input'
).
unbind
(
'change.startUpload'
);
$
(
'.file-input'
).
unbind
(
'change.startUpload'
);
ModalUtils
.
hideModal
();
ModalUtils
.
hideModal
();
if
(
assetsView
.
largeFileErrorMsg
)
{
assetsView
.
largeFileErrorMsg
.
hide
();
}
},
},
showUploadModal
:
function
(
event
)
{
showUploadModal
:
function
(
event
)
{
...
@@ -122,23 +139,44 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -122,23 +139,44 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
$
(
'.upload-modal .file-chooser'
).
fileupload
({
$
(
'.upload-modal .file-chooser'
).
fileupload
({
dataType
:
'json'
,
dataType
:
'json'
,
type
:
'POST'
,
type
:
'POST'
,
maxChunkSize
:
100
*
1000
*
1000
,
// 100 MB
maxChunkSize
:
self
.
uploadChunkSizeInBytes
,
autoUpload
:
true
,
autoUpload
:
true
,
progressall
:
function
(
event
,
data
)
{
progressall
:
function
(
event
,
data
)
{
var
percentComplete
=
parseInt
((
100
*
data
.
loaded
)
/
data
.
total
,
10
);
var
percentComplete
=
parseInt
((
100
*
data
.
loaded
)
/
data
.
total
,
10
);
self
.
showUploadFeedback
(
event
,
percentComplete
);
self
.
showUploadFeedback
(
event
,
percentComplete
);
},
},
maxFileSize
:
100
*
1000
*
1000
,
// 100 MB
maxFileSize
:
self
.
maxFileSizeInBytes
,
maxNumberofFiles
:
100
,
maxNumberofFiles
:
100
,
add
:
function
(
event
,
data
)
{
data
.
process
().
done
(
function
()
{
data
.
submit
();
});
},
done
:
function
(
event
,
data
)
{
done
:
function
(
event
,
data
)
{
self
.
displayFinishedUpload
(
data
.
result
);
self
.
displayFinishedUpload
(
data
.
result
);
}
},
processfail
:
function
(
event
,
data
)
{
var
filename
=
data
.
files
[
data
.
index
].
name
;
var
error
=
gettext
(
"File {filename} exceeds maximum size of {maxFileSizeInMBs} MB"
)
.
replace
(
"{filename}"
,
filename
)
.
replace
(
"{maxFileSizeInMBs}"
,
self
.
maxFileSizeInMBs
)
// disable second part of message for any falsy value,
// which can be null or an empty string
if
(
self
.
maxFileSizeRedirectUrl
)
{
var
instructions
=
gettext
(
"Please follow the instructions here to upload a file elsewhere and link to it: {maxFileSizeRedirectUrl}"
)
.
replace
(
"{maxFileSizeRedirectUrl}"
,
self
.
maxFileSizeRedirectUrl
);
error
=
error
+
" "
+
instructions
;
}
assetsView
.
largeFileErrorMsg
=
new
NotificationView
.
Error
({
"title"
:
gettext
(
"Your file could not be uploaded"
),
"message"
:
error
});
assetsView
.
largeFileErrorMsg
.
show
();
assetsView
.
displayFailedUpload
({
"msg"
:
gettext
(
"Max file size exceeded"
)
});
},
processdone
:
function
(
event
,
data
)
{
assetsView
.
largeFileErrorMsg
=
null
;
}
});
});
},
},
...
@@ -149,11 +187,12 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -149,11 +187,12 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
startUpload
:
function
(
event
)
{
startUpload
:
function
(
event
)
{
var
file
=
event
.
target
.
value
;
var
file
=
event
.
target
.
value
;
if
(
!
assetsView
.
largeFileErrorMsg
)
{
$
(
'.upload-modal h1'
).
text
(
gettext
(
'Uploading…'
));
$
(
'.upload-modal h1'
).
text
(
gettext
(
'Uploading'
));
$
(
'.upload-modal .file-name'
).
html
(
file
.
substring
(
file
.
lastIndexOf
(
"
\
\"
) + 1));
$
(
'.upload-modal .file-name'
).
html
(
file
.
substring
(
file
.
lastIndexOf
(
"
\
\"
) + 1));
$('.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();
}
},
},
resetUploadModal: function () {
resetUploadModal: function () {
...
@@ -169,6 +208,8 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -169,6 +208,8 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
$('.upload-modal .choose-file-button').text(gettext('Choose File'));
$('.upload-modal .choose-file-button').text(gettext('Choose File'));
$('.upload-modal .embeddable-xml-input').val('');
$('.upload-modal .embeddable-xml-input').val('');
$('.upload-modal .embeddable').hide();
$('.upload-modal .embeddable').hide();
assetsView.largeFileErrorMsg = null;
},
},
showUploadFeedback: function (event, percentComplete) {
showUploadFeedback: function (event, percentComplete) {
...
@@ -181,7 +222,7 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -181,7 +222,7 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
var asset = resp.asset;
var asset = resp.asset;
$('.upload-modal h1').text(gettext('Upload New File'));
$('.upload-modal h1').text(gettext('Upload New File'));
$('.upload-modal .embeddable-xml-input').val(asset.portable_url);
$('.upload-modal .embeddable-xml-input').val(asset.portable_url)
.show()
;
$('.upload-modal .embeddable').show();
$('.upload-modal .embeddable').show();
$('.upload-modal .file-name').hide();
$('.upload-modal .file-name').hide();
$('.upload-modal .progress-fill').html(resp.msg);
$('.upload-modal .progress-fill').html(resp.msg);
...
@@ -189,6 +230,16 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
...
@@ -189,6 +230,16 @@ define(["jquery", "underscore", "gettext", "js/models/asset", "js/views/paging",
$('.upload-modal .progress-fill').width('100%');
$('.upload-modal .progress-fill').width('100%');
assetsView.addAsset(new AssetModel(asset));
assetsView.addAsset(new AssetModel(asset));
},
displayFailedUpload: function (resp) {
$('.upload-modal h1').text(gettext('Upload New File'));
$('.upload-modal .embeddable-xml-input').hide();
$('.upload-modal .embeddable').hide();
$('.upload-modal .file-name').hide();
$('.upload-modal .progress-fill').html(resp.msg);
$('.upload-modal .choose-file-button').text(gettext('Load Another File')).show();
$('.upload-modal .progress-fill').width('0%');
}
}
});
});
...
...
This diff is collapsed.
Click to expand it.
cms/static/js_test.yml
View file @
5c433ec9
...
@@ -62,6 +62,10 @@ lib_paths:
...
@@ -62,6 +62,10 @@ lib_paths:
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate.js
# Paths to source JavaScript files
# Paths to source JavaScript files
src_paths
:
src_paths
:
...
...
This diff is collapsed.
Click to expand it.
cms/static/js_test_squire.yml
View file @
5c433ec9
...
@@ -57,6 +57,10 @@ lib_paths:
...
@@ -57,6 +57,10 @@ lib_paths:
-
xmodule_js/common_static/js/test/i18n.js
-
xmodule_js/common_static/js/test/i18n.js
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/coffee/src/xblock/
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/URI.min.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process.js
-
xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate.js
# Paths to source JavaScript files
# Paths to source JavaScript files
src_paths
:
src_paths
:
...
...
This diff is collapsed.
Click to expand it.
cms/static/require-config.js
View file @
5c433ec9
...
@@ -20,6 +20,8 @@ require.config({
...
@@ -20,6 +20,8 @@ require.config({
"jquery.scrollTo"
:
"js/vendor/jquery.scrollTo-1.4.2-min"
,
"jquery.scrollTo"
:
"js/vendor/jquery.scrollTo-1.4.2-min"
,
"jquery.flot"
:
"js/vendor/flot/jquery.flot.min"
,
"jquery.flot"
:
"js/vendor/flot/jquery.flot.min"
,
"jquery.fileupload"
:
"js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.fileupload"
:
"js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.fileupload-process"
:
"js/vendor/jQuery-File-Upload/js/jquery.fileupload-process"
,
"jquery.fileupload-validate"
:
"js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate"
,
"jquery.iframe-transport"
:
"js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.iframe-transport"
:
"js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.inputnumber"
:
"js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.inputnumber"
:
"js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.immediateDescendents"
:
"coffee/src/jquery.immediateDescendents"
,
"jquery.immediateDescendents"
:
"coffee/src/jquery.immediateDescendents"
,
...
@@ -128,9 +130,15 @@ require.config({
...
@@ -128,9 +130,15 @@ require.config({
exports
:
"jQuery.fn.plot"
exports
:
"jQuery.fn.plot"
},
},
"jquery.fileupload"
:
{
"jquery.fileupload"
:
{
deps
:
[
"jquery.iframe-transport"
],
deps
:
[
"jquery.
ui"
,
"jquery.
iframe-transport"
],
exports
:
"jQuery.fn.fileupload"
exports
:
"jQuery.fn.fileupload"
},
},
"jquery.fileupload-process"
:
{
deps
:
[
"jquery.fileupload"
]
},
"jquery.fileupload-validate"
:
{
deps
:
[
"jquery.fileupload"
]
},
"jquery.inputnumber"
:
{
"jquery.inputnumber"
:
{
deps
:
[
"jquery"
],
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.inputNumber"
exports
:
"jQuery.fn.inputNumber"
...
...
This diff is collapsed.
Click to expand it.
cms/templates/asset_index.html
View file @
5c433ec9
...
@@ -19,7 +19,12 @@
...
@@ -19,7 +19,12 @@
<
%
block
name=
"requirejs"
>
<
%
block
name=
"requirejs"
>
require(["js/factories/asset_index"], function (AssetIndexFactory) {
require(["js/factories/asset_index"], function (AssetIndexFactory) {
AssetIndexFactory("${asset_callback_url}");
AssetIndexFactory({
assetCallbackUrl: "${asset_callback_url}",
uploadChunkSizeInMBs: ${chunk_size_in_mbs},
maxFileSizeInMBs: ${max_file_size_in_mbs},
maxFileSizeRedirectUrl: "${max_file_size_redirect_url}"
});
});
});
</
%
block>
</
%
block>
...
@@ -82,6 +87,7 @@
...
@@ -82,6 +87,7 @@
<a
href=
"#"
class=
"close-button"
><i
class=
"icon-remove-sign"
></i>
<span
class=
"sr"
>
${_('close')}
</span></a>
<a
href=
"#"
class=
"close-button"
><i
class=
"icon-remove-sign"
></i>
<span
class=
"sr"
>
${_('close')}
</span></a>
<div
class=
"modal-body"
>
<div
class=
"modal-body"
>
<h1
class=
"title"
>
${_("Upload New File")}
</h1>
<h1
class=
"title"
>
${_("Upload New File")}
</h1>
<h2>
${_("Max per-file size: {max_filesize}MB").format(max_filesize=max_file_size_in_mbs)}
</h2>
<p
class=
"file-name"
>
<p
class=
"file-name"
>
<div
class=
"progress-bar"
>
<div
class=
"progress-bar"
>
<div
class=
"progress-fill"
></div>
<div
class=
"progress-fill"
></div>
...
...
This diff is collapsed.
Click to expand it.
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