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
9d156c04
Commit
9d156c04
authored
Sep 07, 2017
by
Mushtaq Ali
Committed by
muzaffaryousaf
Oct 16, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove course wide transcript settings (N/A provider selected) - EDUCATOR-1311
parent
ec399645
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
178 additions
and
90 deletions
+178
-90
cms/djangoapps/contentstore/views/tests/test_videos.py
+53
-0
cms/djangoapps/contentstore/views/videos.py
+21
-21
cms/static/js/spec/views/course_video_settings_spec.js
+26
-1
cms/static/js/views/course_video_settings.js
+78
-68
No files found.
cms/djangoapps/contentstore/views/tests/test_videos.py
View file @
9d156c04
...
@@ -33,6 +33,7 @@ from contentstore.views.videos import KEY_EXPIRATION_IN_SECONDS, StatusDisplaySt
...
@@ -33,6 +33,7 @@ from contentstore.views.videos import KEY_EXPIRATION_IN_SECONDS, StatusDisplaySt
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
openedx.core.djangoapps.profile_images.tests.helpers
import
make_image_file
from
openedx.core.djangoapps.profile_images.tests.helpers
import
make_image_file
from
edxval.api
import
create_or_update_transcript_preferences
,
get_transcript_preferences
def
override_switch
(
switch
,
active
):
def
override_switch
(
switch
,
active
):
...
@@ -873,6 +874,18 @@ class TranscriptPreferencesTestCase(VideoUploadTestBase, CourseTestCase):
...
@@ -873,6 +874,18 @@ class TranscriptPreferencesTestCase(VideoUploadTestBase, CourseTestCase):
),
),
(
(
{
{
'provider'
:
''
},
'Invalid provider.'
),
(
{
'provider'
:
'dummy-provider'
},
'Invalid provider.'
),
(
{
'provider'
:
TranscriptProvider
.
CIELO24
'provider'
:
TranscriptProvider
.
CIELO24
},
},
'Invalid cielo24 fidelity.'
'Invalid cielo24 fidelity.'
...
@@ -970,6 +983,46 @@ class TranscriptPreferencesTestCase(VideoUploadTestBase, CourseTestCase):
...
@@ -970,6 +983,46 @@ class TranscriptPreferencesTestCase(VideoUploadTestBase, CourseTestCase):
self
.
assertEqual
(
status_code
,
200
)
self
.
assertEqual
(
status_code
,
200
)
self
.
assertTrue
(
response
[
'transcript_preferences'
],
preferences_data
)
self
.
assertTrue
(
response
[
'transcript_preferences'
],
preferences_data
)
def
test_remove_transcript_preferences
(
self
):
"""
Test that transcript handler removes transcript preferences correctly.
"""
# First add course wide transcript preferences.
preferences
=
create_or_update_transcript_preferences
(
unicode
(
self
.
course
.
id
))
# Verify transcript preferences exist
self
.
assertIsNotNone
(
preferences
)
response
=
self
.
client
.
delete
(
self
.
get_url_for_course_key
(
self
.
course
.
id
),
content_type
=
'application/json'
)
self
.
assertEqual
(
response
.
status_code
,
204
)
# Verify transcript preferences no loger exist
preferences
=
get_transcript_preferences
(
unicode
(
self
.
course
.
id
))
self
.
assertIsNone
(
preferences
)
def
test_remove_transcript_preferences_not_found
(
self
):
"""
Test that transcript handler works correctly even when no preferences are found.
"""
course_id
=
'dummy+course+id'
# Verify transcript preferences do not exist
preferences
=
get_transcript_preferences
(
course_id
)
self
.
assertIsNone
(
preferences
)
response
=
self
.
client
.
delete
(
self
.
get_url_for_course_key
(
course_id
),
content_type
=
'application/json'
)
self
.
assertEqual
(
response
.
status_code
,
204
)
# Verify transcript preferences do not exist
preferences
=
get_transcript_preferences
(
course_id
)
self
.
assertIsNone
(
preferences
)
@ddt.data
(
@ddt.data
(
None
,
None
,
{
{
...
...
cms/djangoapps/contentstore/views/videos.py
View file @
9d156c04
...
@@ -30,6 +30,7 @@ from edxval.api import (
...
@@ -30,6 +30,7 @@ from edxval.api import (
get_3rd_party_transcription_plans
,
get_3rd_party_transcription_plans
,
get_transcript_preferences
,
get_transcript_preferences
,
create_or_update_transcript_preferences
,
create_or_update_transcript_preferences
,
remove_transcript_preferences
,
)
)
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
from
openedx.core.djangoapps.waffle_utils
import
WaffleSwitchNamespace
from
openedx.core.djangoapps.waffle_utils
import
WaffleSwitchNamespace
...
@@ -327,7 +328,7 @@ def validate_transcript_preferences(
...
@@ -327,7 +328,7 @@ def validate_transcript_preferences(
@expect_json
@expect_json
@login_required
@login_required
@require_
POST
@require_
http_methods
((
'POST'
,
'DELETE'
))
def
transcript_preferences_handler
(
request
,
course_key_string
):
def
transcript_preferences_handler
(
request
,
course_key_string
):
"""
"""
JSON view handler to post the transcript preferences.
JSON view handler to post the transcript preferences.
...
@@ -338,26 +339,25 @@ def transcript_preferences_handler(request, course_key_string):
...
@@ -338,26 +339,25 @@ def transcript_preferences_handler(request, course_key_string):
Returns: valid json response or 400 with error message
Returns: valid json response or 400 with error message
"""
"""
data
=
request
.
json
if
request
.
method
==
'POST'
:
provider
=
data
.
get
(
'provider'
,
''
)
data
=
request
.
json
provider
=
data
.
get
(
'provider'
)
# TODO: if provider == '': delete course preferences
error
,
preferences
=
validate_transcript_preferences
(
# i.e call delete api end point like delete_transcript_preferences(course_key_string)
provider
=
provider
,
cielo24_fidelity
=
data
.
get
(
'cielo24_fidelity'
,
''
),
error
,
preferences
=
validate_transcript_preferences
(
cielo24_turnaround
=
data
.
get
(
'cielo24_turnaround'
,
''
),
provider
=
provider
,
three_play_turnaround
=
data
.
get
(
'three_play_turnaround'
,
''
),
cielo24_fidelity
=
data
.
get
(
'cielo24_fidelity'
,
''
),
preferred_languages
=
data
.
get
(
'preferred_languages'
,
[])
cielo24_turnaround
=
data
.
get
(
'cielo24_turnaround'
,
''
),
)
three_play_turnaround
=
data
.
get
(
'three_play_turnaround'
,
''
),
if
error
:
preferred_languages
=
data
.
get
(
'preferred_languages'
,
[])
response
=
JsonResponse
({
'error'
:
error
},
status
=
400
)
)
else
:
preferences
.
update
({
'provider'
:
provider
})
if
error
:
transcript_preferences
=
create_or_update_transcript_preferences
(
course_key_string
,
**
preferences
)
response
=
JsonResponse
({
'error'
:
error
},
status
=
400
)
response
=
JsonResponse
({
'transcript_preferences'
:
transcript_preferences
},
status
=
200
)
else
:
elif
request
.
method
==
'DELETE'
:
preferences
.
update
({
'provider'
:
provider
})
remove_transcript_preferences
(
course_key_string
)
transcript_preferences
=
create_or_update_transcript_preferences
(
course_key_string
,
**
preferences
)
response
=
JsonResponse
()
response
=
JsonResponse
({
'transcript_preferences'
:
transcript_preferences
},
status
=
200
)
return
response
return
response
...
...
cms/static/js/spec/views/course_video_settings_spec.js
View file @
9d156c04
...
@@ -186,7 +186,7 @@ define(
...
@@ -186,7 +186,7 @@ define(
})
})
);
);
// Send successful
upload
response.
// Send successful response.
AjaxHelpers
.
respondWithJson
(
requests
,
{
AjaxHelpers
.
respondWithJson
(
requests
,
{
transcript_preferences
:
activeTranscriptPreferences
transcript_preferences
:
activeTranscriptPreferences
});
});
...
@@ -200,6 +200,31 @@ define(
...
@@ -200,6 +200,31 @@ define(
);
);
});
});
it
(
'removes transcript settings on update settings button click when no provider is selected'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
// Set no provider selected
courseVideoSettingsView
.
selectedProvider
=
null
;
$courseVideoSettingsEl
.
find
(
'.action-update-course-video-settings'
).
click
();
AjaxHelpers
.
expectRequest
(
requests
,
'DELETE'
,
transcriptPreferencesUrl
);
// Send successful empty content response.
AjaxHelpers
.
respondWithJson
(
requests
,
{});
// Verify that success message is shown.
expect
(
$courseVideoSettingsEl
.
find
(
'.course-video-settings-message-wrapper.success'
).
html
()).
toEqual
(
'<div class="course-video-settings-message">'
+
'<span class="icon fa fa-check-circle" aria-hidden="true"></span>'
+
'<span>Settings updated</span>'
+
'</div>'
);
});
it
(
'shows error message if server sends error'
,
function
()
{
it
(
'shows error message if server sends error'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
requests
=
AjaxHelpers
.
requests
(
this
);
$courseVideoSettingsEl
.
find
(
'.action-update-course-video-settings'
).
click
();
$courseVideoSettingsEl
.
find
(
'.action-update-course-video-settings'
).
click
();
...
...
cms/static/js/views/course_video_settings.js
View file @
9d156c04
...
@@ -336,6 +336,43 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
...
@@ -336,6 +336,43 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
);
);
},
},
updateSuccessResponseStatus
:
function
(
data
)
{
this
.
renderResponseStatus
(
gettext
(
'Settings updated'
),
'success'
);
// Sync ActiveUploadListView with latest active plan.
this
.
activeTranscriptionPlan
=
data
;
Backbone
.
trigger
(
'coursevideosettings:syncActiveTranscriptPreferences'
,
this
.
activeTranscriptionPlan
);
},
updateFailResponseStatus
:
function
(
data
)
{
var
errorMessage
;
// Enclose inside try-catch so that if we get erroneous data, we could still
// show some error to user
try
{
errorMessage
=
$
.
parseJSON
(
data
).
error
;
}
catch
(
e
)
{}
// eslint-disable-line no-empty
errorMessage
=
errorMessage
||
gettext
(
'Error saving data'
);
this
.
renderResponseStatus
(
errorMessage
,
'error'
);
},
renderResponseStatus
:
function
(
responseText
,
type
)
{
var
addClass
=
type
===
'error'
?
'error'
:
'success'
,
removeClass
=
type
===
'error'
?
'success'
:
'error'
,
iconClass
=
type
===
'error'
?
'fa-info-circle'
:
'fa-check-circle'
,
$messageWrapperEl
=
this
.
$el
.
find
(
'.course-video-settings-message-wrapper'
);
$messageWrapperEl
.
removeClass
(
removeClass
);
$messageWrapperEl
.
addClass
(
addClass
);
HtmlUtils
.
setHtml
(
$messageWrapperEl
,
HtmlUtils
.
interpolateHtml
(
HtmlUtils
.
HTML
(
'<div class="course-video-settings-message"><span class="icon fa {iconClass}" aria-hidden="true"></span><span>{text}</span></div>'
),
// eslint-disable-line max-len
{
text
:
responseText
,
iconClass
:
iconClass
}
)
);
},
clearResponseStatus
:
function
()
{
clearResponseStatus
:
function
()
{
// Remove parent level state.
// Remove parent level state.
var
$messageWrapperEl
=
this
.
$el
.
find
(
'.course-video-settings-message-wrapper'
);
var
$messageWrapperEl
=
this
.
$el
.
find
(
'.course-video-settings-message-wrapper'
);
...
@@ -407,59 +444,38 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
...
@@ -407,59 +444,38 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
saveTranscriptPreferences
:
function
()
{
saveTranscriptPreferences
:
function
()
{
var
self
=
this
,
var
self
=
this
,
$messageWrapperEl
=
self
.
$el
.
find
(
'.course-video-settings-message-wrapper'
);
responseTranscriptPreferences
;
// First clear response status if present already
// First clear response status if present already
this
.
clearResponseStatus
();
this
.
clearResponseStatus
();
$
.
postJSON
(
this
.
transcriptHandlerUrl
,
{
if
(
self
.
selectedProvider
)
{
provider
:
self
.
selectedProvider
,
$
.
postJSON
(
self
.
transcriptHandlerUrl
,
{
cielo24_fidelity
:
self
.
selectedFidelityPlan
,
provider
:
self
.
selectedProvider
,
cielo24_turnaround
:
self
.
selectedProvider
===
CIELO24
?
self
.
selectedTurnaroundPlan
:
''
,
cielo24_fidelity
:
self
.
selectedFidelityPlan
,
three_play_turnaround
:
self
.
selectedProvider
===
THREE_PLAY_MEDIA
?
self
.
selectedTurnaroundPlan
:
''
,
cielo24_turnaround
:
self
.
selectedProvider
===
CIELO24
?
self
.
selectedTurnaroundPlan
:
''
,
preferred_languages
:
self
.
selectedLanguages
,
three_play_turnaround
:
self
.
selectedProvider
===
THREE_PLAY_MEDIA
?
self
.
selectedTurnaroundPlan
:
''
,
// eslint-disable-line max-len
global
:
false
// Do not trigger global AJAX error handler
preferred_languages
:
self
.
selectedLanguages
,
},
function
(
data
)
{
global
:
false
// Do not trigger global AJAX error handler
if
(
data
.
transcript_preferences
)
{
},
function
(
data
)
{
$messageWrapperEl
.
removeClass
(
'error'
);
responseTranscriptPreferences
=
data
?
data
.
transcript_preferences
:
null
;
$messageWrapperEl
.
addClass
(
'success'
);
self
.
updateSuccessResponseStatus
(
responseTranscriptPreferences
);
HtmlUtils
.
setHtml
(
}).
fail
(
function
(
jqXHR
)
{
$messageWrapperEl
,
if
(
jqXHR
.
responseText
)
{
HtmlUtils
.
interpolateHtml
(
self
.
updateFailResponseStatus
(
jqXHR
.
responseText
);
HtmlUtils
.
HTML
(
'<div class="course-video-settings-message"><span class="icon fa fa-check-circle" aria-hidden="true"></span><span>{text}</span></div>'
),
// eslint-disable-line max-len
}
{
});
text
:
gettext
(
'Settings updated'
)
}
else
{
}
$
.
ajax
({
)
type
:
'DELETE'
,
);
url
:
self
.
transcriptHandlerUrl
self
.
activeTranscriptionPlan
=
data
.
transcript_preferences
;
}).
done
(
function
()
{
self
.
updateSuccessResponseStatus
(
null
);
// Sync ActiveUploadListView with latest active plan.
}).
fail
(
function
(
jqXHR
)
{
Backbone
.
trigger
(
if
(
jqXHR
.
responseText
)
{
'coursevideosettings:syncActiveTranscriptPreferences'
,
self
.
updateFailResponseStatus
(
jqXHR
.
responseText
);
self
.
activeTranscriptionPlan
}
);
});
}
}
}).
fail
(
function
(
jqXHR
)
{
var
errorMessage
;
if
(
jqXHR
.
responseText
)
{
// Enclose inside try-catch so that if we get erroneous data, we could still show some error to user
try
{
errorMessage
=
$
.
parseJSON
(
jqXHR
.
responseText
).
error
;
}
catch
(
e
)
{}
// eslint-disable-line no-empty
$messageWrapperEl
.
removeClass
(
'success'
);
$messageWrapperEl
.
addClass
(
'error'
);
HtmlUtils
.
setHtml
(
$messageWrapperEl
,
HtmlUtils
.
interpolateHtml
(
HtmlUtils
.
HTML
(
'<div class="course-video-settings-message"><span class="icon fa fa-info-circle" aria-hidden="true"></span><span>{text}</span></div>'
),
// eslint-disable-line max-len
{
text
:
errorMessage
||
gettext
(
'Error saving data'
)
}
)
);
}
});
},
},
updateCourseVideoSettings
:
function
()
{
updateCourseVideoSettings
:
function
()
{
...
@@ -489,35 +505,29 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
...
@@ -489,35 +505,29 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
},
},
setFixedCourseVideoSettingsPane
:
function
()
{
setFixedCourseVideoSettingsPane
:
function
()
{
var
windowWidth
=
$
(
window
).
width
(),
var
$courseVideoSettingsButton
=
$
(
'.course-video-settings-button'
),
windowHeight
=
$
(
window
).
height
(),
$courseVideoSettingsButton
=
$
(
'.course-video-settings-button'
),
$courseVideoSettingsContainer
=
this
.
$el
.
find
(
'.course-video-settings-container'
),
$courseVideoSettingsContainer
=
this
.
$el
.
find
(
'.course-video-settings-container'
),
initialPositionTop
=
$courseVideoSettingsContainer
.
offset
().
top
,
initialPositionTop
=
$courseVideoSettingsContainer
.
offset
().
top
,
courseVideoSettingsButtonLeft
=
$courseVideoSettingsButton
.
offset
().
left
,
// Button right position = width of window - button left position - button width - paddings - border.
fixedOffsetRight
=
windowWidth
-
$courseVideoSettingsButtonRight
=
$
(
window
).
width
()
-
courseVideoSettingsButtonLeft
-
$courseVideoSettingsButton
.
width
()
-
25
;
$courseVideoSettingsButton
.
offset
().
left
-
$courseVideoSettingsButton
.
width
()
-
$courseVideoSettingsButton
.
css
(
'padding-left'
).
replace
(
'px'
,
''
)
-
$courseVideoSettingsButton
.
css
(
'padding-right'
).
replace
(
'px'
,
''
)
-
$courseVideoSettingsButton
.
css
(
'border-width'
).
replace
(
'px'
,
''
)
-
5
;
// Extra pixles for slack;
// set windows total height
// Set to windows total height
$courseVideoSettingsContainer
.
css
(
'height'
,
windowHeight
);
$courseVideoSettingsContainer
.
css
(
'height'
,
$
(
window
).
height
());
$courseVideoSettingsContainer
.
css
(
'right'
,
20
);
// Start settings pane adjascent to 'course video settings' button.
$courseVideoSettingsContainer
.
css
(
'right'
,
$courseVideoSettingsButtonRight
);
// Make sticky when scroll reaches top.
// Make sticky when scroll reaches top.
$
(
window
).
scroll
(
function
()
{
$
(
window
).
scroll
(
function
()
{
// Remove transition when we start scrolling.
// Why we do this? The settings pane come back and forth when it is switched between
// position:fixed and position:absolute, it's right and top position are then being changed wrt to their
// position layout.
$courseVideoSettingsContainer
.
css
(
'transition'
,
'none'
);
if
(
$
(
window
).
scrollTop
()
>=
initialPositionTop
)
{
if
(
$
(
window
).
scrollTop
()
>=
initialPositionTop
)
{
$courseVideoSettingsContainer
.
addClass
(
'fixed-container'
);
$courseVideoSettingsContainer
.
addClass
(
'fixed-container'
);
// TODO: Removes these js calculations and try to do through CSS way.
$courseVideoSettingsContainer
.
css
(
'right'
,
fixedOffsetRight
);
}
else
{
}
else
{
$courseVideoSettingsContainer
.
removeClass
(
'fixed-container'
);
$courseVideoSettingsContainer
.
removeClass
(
'fixed-container'
);
$courseVideoSettingsContainer
.
css
(
'right'
,
20
);
}
}
});
});
},
},
...
...
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