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
68e1985d
Commit
68e1985d
authored
Dec 05, 2013
by
Anton Stupak
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1807 from edx/anton/transcripts
Video Transcripts: Fix clear and download buttons.
parents
beda1f8b
b4f82b38
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
86 additions
and
43 deletions
+86
-43
CHANGELOG.rst
+2
-0
cms/djangoapps/contentstore/features/transcripts.feature
+22
-0
cms/djangoapps/contentstore/features/transcripts.py
+43
-40
cms/djangoapps/contentstore/transcripts_utils.py
+7
-1
cms/static/js/views/transcripts/editor.js
+11
-1
cms/templates/js/transcripts/messages/transcripts-uploaded.underscore
+1
-1
No files found.
CHANGELOG.rst
View file @
68e1985d
...
@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
...
@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
the top. Include a label indicating the component affected.
Blades: Video Transcripts: Fix clear and download buttons. BLD-438.
Common: Switch over from MITX_FEATURES to just FEATURES. To override items in
Common: Switch over from MITX_FEATURES to just FEATURES. To override items in
the FEATURES dict, the environment variable you must set to do so is also
the FEATURES dict, the environment variable you must set to do so is also
now called FEATURES instead of MITX_FEATURES.
now called FEATURES instead of MITX_FEATURES.
...
...
cms/djangoapps/contentstore/features/transcripts.feature
View file @
68e1985d
...
@@ -653,3 +653,25 @@ Feature: Video Component Editor
...
@@ -653,3 +653,25 @@ Feature: Video Component Editor
Then
when I view the video it does show the captions
Then
when I view the video it does show the captions
And I see "LILA FISHER
:
Hi,
welcome
to
Edx."
text
in
the
captions
And I see "LILA FISHER
:
Hi,
welcome
to
Edx."
text
in
the
captions
#35
Scenario
:
After reverting Transcripts field in the Advanced tab "not found" message should be visible
Given
I have created a Video component
And
I edit the component
And
I enter a
"t_not_exist.mp4"
source to field number 1
Then
I see status message
"not found"
And
I upload the transcripts file
"chinese_transcripts.srt"
Then
I see status message
"uploaded_successfully"
And
I save changes
Then
I see
"好 各位同学"
text in the captions
And
I edit the component
And
I open tab
"Advanced"
And
I revert the transcript field"HTML5 Transcript"
And
I save changes
Then
when I view the video it does not show the captions
And
I edit the component
Then
I see status message
"not found"
cms/djangoapps/contentstore/features/transcripts.py
View file @
68e1985d
...
@@ -9,7 +9,7 @@ from django.conf import settings
...
@@ -9,7 +9,7 @@ from django.conf import settings
from
xmodule.contentstore.content
import
StaticContent
from
xmodule.contentstore.content
import
StaticContent
from
xmodule.contentstore.django
import
contentstore
from
xmodule.contentstore.django
import
contentstore
from
xmodule.exceptions
import
NotFoundError
from
xmodule.exceptions
import
NotFoundError
from
splinter.request_handler.request_handler
import
RequestHandler
TEST_ROOT
=
settings
.
COMMON_TEST_DATA_ROOT
TEST_ROOT
=
settings
.
COMMON_TEST_DATA_ROOT
...
@@ -49,6 +49,13 @@ TRANSCRIPTS_BUTTONS = {
...
@@ -49,6 +49,13 @@ TRANSCRIPTS_BUTTONS = {
}
}
def
_clear_field
(
index
):
world
.
css_fill
(
SELECTORS
[
'url_inputs'
],
''
,
index
)
# In some reason chromeDriver doesn't trigger 'input' event after filling
# field by an empty value. That's why we trigger it manually via jQuery.
world
.
trigger_event
(
SELECTORS
[
'url_inputs'
],
event
=
'input'
,
index
=
index
)
@step
(
'I clear fields$'
)
@step
(
'I clear fields$'
)
def
clear_fields
(
_step
):
def
clear_fields
(
_step
):
js_str
=
'''
js_str
=
'''
...
@@ -60,16 +67,18 @@ def clear_fields(_step):
...
@@ -60,16 +67,18 @@ def clear_fields(_step):
for
index
in
range
(
1
,
4
):
for
index
in
range
(
1
,
4
):
js
=
js_str
.
format
(
selector
=
SELECTORS
[
'url_inputs'
],
index
=
index
-
1
)
js
=
js_str
.
format
(
selector
=
SELECTORS
[
'url_inputs'
],
index
=
index
-
1
)
world
.
browser
.
execute_script
(
js
)
world
.
browser
.
execute_script
(
js
)
_step
.
given
(
'I clear field number {0}'
.
format
(
index
))
_clear_field
(
index
)
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
@step
(
'I clear field number (.+)$'
)
@step
(
'I clear field number (.+)$'
)
def
clear_field
(
_step
,
index
):
def
clear_field
(
_step
,
index
):
index
=
int
(
index
)
-
1
index
=
int
(
index
)
-
1
world
.
css_fill
(
SELECTORS
[
'url_inputs'
],
''
,
index
)
_clear_field
(
index
)
# In some reason chromeDriver doesn't trigger 'input' event after filling
world
.
wait
(
DELAY
)
# field by an empty value. That's why we trigger it manually via jQuery.
world
.
wait_for_ajax_complete
()
world
.
trigger_event
(
SELECTORS
[
'url_inputs'
],
event
=
'input'
,
index
=
index
)
@step
(
'I expect (.+) inputs are disabled$'
)
@step
(
'I expect (.+) inputs are disabled$'
)
...
@@ -91,40 +100,32 @@ def inputs_are_enabled(_step):
...
@@ -91,40 +100,32 @@ def inputs_are_enabled(_step):
@step
(
'I do not see error message$'
)
@step
(
'I do not see error message$'
)
def
i_do_not_see_error_message
(
_step
):
def
i_do_not_see_error_message
(
_step
):
world
.
wait
(
DELAY
)
assert
not
world
.
css_visible
(
SELECTORS
[
'error_bar'
])
assert
not
world
.
css_visible
(
SELECTORS
[
'error_bar'
])
@step
(
'I see error message "([^"]*)"$'
)
@step
(
'I see error message "([^"]*)"$'
)
def
i_see_error_message
(
_step
,
error
):
def
i_see_error_message
(
_step
,
error
):
world
.
wait
(
DELAY
)
assert
world
.
css_has_text
(
SELECTORS
[
'error_bar'
],
ERROR_MESSAGES
[
error
.
strip
()])
assert
world
.
css_has_text
(
SELECTORS
[
'error_bar'
],
ERROR_MESSAGES
[
error
.
strip
()])
@step
(
'I do not see status message$'
)
@step
(
'I do not see status message$'
)
def
i_do_not_see_status_message
(
_step
):
def
i_do_not_see_status_message
(
_step
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
assert
not
world
.
css_visible
(
SELECTORS
[
'status_bar'
])
assert
not
world
.
css_visible
(
SELECTORS
[
'status_bar'
])
@step
(
'I see status message "([^"]*)"$'
)
@step
(
'I see status message "([^"]*)"$'
)
def
i_see_status_message
(
_step
,
status
):
def
i_see_status_message
(
_step
,
status
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
assert
not
world
.
css_visible
(
SELECTORS
[
'error_bar'
])
assert
not
world
.
css_visible
(
SELECTORS
[
'error_bar'
])
assert
world
.
css_has_text
(
SELECTORS
[
'status_bar'
],
STATUSES
[
status
.
strip
()])
assert
world
.
css_has_text
(
SELECTORS
[
'status_bar'
],
STATUSES
[
status
.
strip
()])
DOWNLOAD_BUTTON
=
TRANSCRIPTS_BUTTONS
[
"download_to_edit"
][
0
]
if
world
.
is_css_present
(
DOWNLOAD_BUTTON
,
wait_time
=
1
)
\
and
not
world
.
css_find
(
DOWNLOAD_BUTTON
)[
0
]
.
has_class
(
'is-disabled'
):
assert
_transcripts_are_downloaded
()
@step
(
'I (.*)see button "([^"]*)"$'
)
@step
(
'I (.*)see button "([^"]*)"$'
)
def
i_see_button
(
_step
,
not_see
,
button_type
):
def
i_see_button
(
_step
,
not_see
,
button_type
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
button
=
button_type
.
strip
()
button
=
button_type
.
strip
()
if
not_see
.
strip
():
if
not_see
.
strip
():
...
@@ -135,9 +136,6 @@ def i_see_button(_step, not_see, button_type):
...
@@ -135,9 +136,6 @@ def i_see_button(_step, not_see, button_type):
@step
(
'I (.*)see (.*)button "([^"]*)" number (
\
d+)$'
)
@step
(
'I (.*)see (.*)button "([^"]*)" number (
\
d+)$'
)
def
i_see_button_with_custom_text
(
_step
,
not_see
,
button_type
,
custom_text
,
index
):
def
i_see_button_with_custom_text
(
_step
,
not_see
,
button_type
,
custom_text
,
index
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
button
=
button_type
.
strip
()
button
=
button_type
.
strip
()
custom_text
=
custom_text
.
strip
()
custom_text
=
custom_text
.
strip
()
index
=
int
(
index
.
strip
())
-
1
index
=
int
(
index
.
strip
())
-
1
...
@@ -150,22 +148,18 @@ def i_see_button_with_custom_text(_step, not_see, button_type, custom_text, inde
...
@@ -150,22 +148,18 @@ def i_see_button_with_custom_text(_step, not_see, button_type, custom_text, inde
@step
(
'I click transcript button "([^"]*)"$'
)
@step
(
'I click transcript button "([^"]*)"$'
)
def
click_button_transcripts_variant
(
_step
,
button_type
):
def
click_button_transcripts_variant
(
_step
,
button_type
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
button
=
button_type
.
strip
()
button
=
button_type
.
strip
()
world
.
css_click
(
TRANSCRIPTS_BUTTONS
[
button
][
0
])
world
.
css_click
(
TRANSCRIPTS_BUTTONS
[
button
][
0
])
world
.
wait_for_ajax_complete
()
@step
(
'I click transcript button "([^"]*)" number (
\
d+)$'
)
@step
(
'I click transcript button "([^"]*)" number (
\
d+)$'
)
def
click_button_index
(
_step
,
button_type
,
index
):
def
click_button_index
(
_step
,
button_type
,
index
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
button
=
button_type
.
strip
()
button
=
button_type
.
strip
()
index
=
int
(
index
.
strip
())
-
1
index
=
int
(
index
.
strip
())
-
1
world
.
css_click
(
TRANSCRIPTS_BUTTONS
[
button
][
0
],
index
)
world
.
css_click
(
TRANSCRIPTS_BUTTONS
[
button
][
0
],
index
)
world
.
wait_for_ajax_complete
()
@step
(
'I remove "([^"]+)" transcripts id from store'
)
@step
(
'I remove "([^"]+)" transcripts id from store'
)
...
@@ -187,9 +181,6 @@ def remove_transcripts_from_store(_step, subs_id):
...
@@ -187,9 +181,6 @@ def remove_transcripts_from_store(_step, subs_id):
@step
(
'I enter a "([^"]+)" source to field number (
\
d+)$'
)
@step
(
'I enter a "([^"]+)" source to field number (
\
d+)$'
)
def
i_enter_a_source
(
_step
,
link
,
index
):
def
i_enter_a_source
(
_step
,
link
,
index
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
index
=
int
(
index
)
-
1
index
=
int
(
index
)
-
1
if
index
is
not
0
and
not
world
.
css_visible
(
SELECTORS
[
'collapse_bar'
]):
if
index
is
not
0
and
not
world
.
css_visible
(
SELECTORS
[
'collapse_bar'
]):
...
@@ -198,6 +189,8 @@ def i_enter_a_source(_step, link, index):
...
@@ -198,6 +189,8 @@ def i_enter_a_source(_step, link, index):
assert
world
.
css_visible
(
SELECTORS
[
'collapse_bar'
])
assert
world
.
css_visible
(
SELECTORS
[
'collapse_bar'
])
world
.
css_fill
(
SELECTORS
[
'url_inputs'
],
link
,
index
)
world
.
css_fill
(
SELECTORS
[
'url_inputs'
],
link
,
index
)
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
@step
(
'I upload the transcripts file "([^"]*)"$'
)
@step
(
'I upload the transcripts file "([^"]*)"$'
)
...
@@ -205,6 +198,7 @@ def upload_file(_step, file_name):
...
@@ -205,6 +198,7 @@ def upload_file(_step, file_name):
path
=
os
.
path
.
join
(
TEST_ROOT
,
'uploads/'
,
file_name
.
strip
())
path
=
os
.
path
.
join
(
TEST_ROOT
,
'uploads/'
,
file_name
.
strip
())
world
.
browser
.
execute_script
(
"$('form.file-chooser').show()"
)
world
.
browser
.
execute_script
(
"$('form.file-chooser').show()"
)
world
.
browser
.
attach_file
(
'file'
,
os
.
path
.
abspath
(
path
))
world
.
browser
.
attach_file
(
'file'
,
os
.
path
.
abspath
(
path
))
world
.
wait_for_ajax_complete
()
@step
(
'I see "([^"]*)" text in the captions'
)
@step
(
'I see "([^"]*)" text in the captions'
)
...
@@ -214,9 +208,6 @@ def check_text_in_the_captions(_step, text):
...
@@ -214,9 +208,6 @@ def check_text_in_the_captions(_step, text):
@step
(
'I see value "([^"]*)" in the field "([^"]*)"$'
)
@step
(
'I see value "([^"]*)" in the field "([^"]*)"$'
)
def
check_transcripts_field
(
_step
,
values
,
field_name
):
def
check_transcripts_field
(
_step
,
values
,
field_name
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
world
.
click_link_by_text
(
'Advanced'
)
world
.
click_link_by_text
(
'Advanced'
)
field_id
=
'#'
+
world
.
browser
.
find_by_xpath
(
'//label[text()="
%
s"]'
%
field_name
.
strip
())[
0
][
'for'
]
field_id
=
'#'
+
world
.
browser
.
find_by_xpath
(
'//label[text()="
%
s"]'
%
field_name
.
strip
())[
0
][
'for'
]
values_list
=
[
i
.
strip
()
==
world
.
css_value
(
field_id
)
for
i
in
values
.
split
(
'|'
)]
values_list
=
[
i
.
strip
()
==
world
.
css_value
(
field_id
)
for
i
in
values
.
split
(
'|'
)]
...
@@ -226,22 +217,34 @@ def check_transcripts_field(_step, values, field_name):
...
@@ -226,22 +217,34 @@ def check_transcripts_field(_step, values, field_name):
@step
(
'I save changes$'
)
@step
(
'I save changes$'
)
def
save_changes
(
_step
):
def
save_changes
(
_step
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
save_css
=
'a.save-button'
save_css
=
'a.save-button'
world
.
css_click
(
save_css
)
world
.
css_click
(
save_css
)
world
.
wait_for_ajax_complete
()
@step
(
'I open tab "([^"]*)"$'
)
@step
(
'I open tab "([^"]*)"$'
)
def
open_tab
(
_step
,
tab_name
):
def
open_tab
(
_step
,
tab_name
):
world
.
click_link_by_text
(
tab_name
.
strip
())
world
.
click_link_by_text
(
tab_name
.
strip
())
world
.
wait_for_ajax_complete
()
@step
(
'I set value "([^"]*)" to the field "([^"]*)"$'
)
@step
(
'I set value "([^"]*)" to the field "([^"]*)"$'
)
def
set_value_transcripts_field
(
_step
,
value
,
field_name
):
def
set_value_transcripts_field
(
_step
,
value
,
field_name
):
world
.
wait
(
DELAY
)
world
.
wait_for_ajax_complete
()
field_id
=
'#'
+
world
.
browser
.
find_by_xpath
(
'//label[text()="
%
s"]'
%
field_name
.
strip
())[
0
][
'for'
]
field_id
=
'#'
+
world
.
browser
.
find_by_xpath
(
'//label[text()="
%
s"]'
%
field_name
.
strip
())[
0
][
'for'
]
world
.
css_fill
(
field_id
,
value
.
strip
())
world
.
css_fill
(
field_id
,
value
.
strip
())
world
.
wait_for_ajax_complete
()
@step
(
'I revert the transcript field "([^"]*)"$'
)
def
revert_transcripts_field
(
_step
,
field_name
):
world
.
revert_setting_entry
(
field_name
)
def
_transcripts_are_downloaded
():
world
.
wait_for_ajax_complete
()
request
=
RequestHandler
()
DOWNLOAD_BUTTON
=
world
.
css_find
(
TRANSCRIPTS_BUTTONS
[
"download_to_edit"
][
0
])
.
first
url
=
DOWNLOAD_BUTTON
[
'href'
]
request
.
connect
(
url
)
return
request
.
status_code
.
is_success
()
cms/djangoapps/contentstore/transcripts_utils.py
View file @
68e1985d
...
@@ -196,6 +196,7 @@ def remove_subs_from_store(subs_id, item):
...
@@ -196,6 +196,7 @@ def remove_subs_from_store(subs_id, item):
try
:
try
:
content
=
contentstore
()
.
find
(
content_location
)
content
=
contentstore
()
.
find
(
content_location
)
contentstore
()
.
delete
(
content
.
get_id
())
contentstore
()
.
delete
(
content
.
get_id
())
del_cached_content
(
content
.
location
)
log
.
info
(
"Removed subs
%
s from store"
,
subs_id
)
log
.
info
(
"Removed subs
%
s from store"
,
subs_id
)
except
NotFoundError
:
except
NotFoundError
:
pass
pass
...
@@ -310,7 +311,9 @@ def manage_video_subtitles_save(old_item, new_item):
...
@@ -310,7 +311,9 @@ def manage_video_subtitles_save(old_item, new_item):
Video player item has some video fields: HTML5 ones and Youtube one.
Video player item has some video fields: HTML5 ones and Youtube one.
1. If value of `sub` field of `new_item` is different from values of video fields of `new_item`,
If value of `sub` field of `new_item` is cleared, transcripts should be removed.
If value of `sub` field of `new_item` is different from values of video fields of `new_item`,
and `new_item.sub` file is present, then code in this function creates copies of
and `new_item.sub` file is present, then code in this function creates copies of
`new_item.sub` file with new names. That names are equal to values of video fields of `new_item`
`new_item.sub` file with new names. That names are equal to values of video fields of `new_item`
After that `sub` field of `new_item` is changed to one of values of video fields.
After that `sub` field of `new_item` is changed to one of values of video fields.
...
@@ -328,6 +331,9 @@ def manage_video_subtitles_save(old_item, new_item):
...
@@ -328,6 +331,9 @@ def manage_video_subtitles_save(old_item, new_item):
for
video_id
in
possible_video_id_list
:
for
video_id
in
possible_video_id_list
:
if
not
video_id
:
if
not
video_id
:
continue
continue
if
not
sub_name
:
remove_subs_from_store
(
video_id
,
new_item
)
continue
# copy_or_rename_transcript changes item.sub of module
# copy_or_rename_transcript changes item.sub of module
try
:
try
:
# updates item.sub with `video_id`, if it is successful.
# updates item.sub with `video_id`, if it is successful.
...
...
cms/static/js/views/transcripts/editor.js
View file @
68e1985d
...
@@ -90,7 +90,17 @@ function($, Backbone, _, Utils, MetadataView, MetadataCollection) {
...
@@ -90,7 +90,17 @@ function($, Backbone, _, Utils, MetadataView, MetadataCollection) {
var
isSubsModified
=
(
function
(
values
)
{
var
isSubsModified
=
(
function
(
values
)
{
var
isSubsChanged
=
subs
.
hasChanged
(
"value"
);
var
isSubsChanged
=
subs
.
hasChanged
(
"value"
);
return
Boolean
(
isSubsChanged
&&
_
.
isString
(
values
.
sub
));
return
Boolean
(
isSubsChanged
&&
(
// If the user changes the field, `values.sub` contains
// string value;
// If the user clicks `clear` button, the field contains
// null value.
// Otherwise, undefined.
_
.
isString
(
values
.
sub
)
||
_
.
isNull
(
subs
.
getValue
())
)
);
}(
modifiedValues
));
}(
modifiedValues
));
// When we change value of `sub` field in the `Advanced`,
// When we change value of `sub` field in the `Advanced`,
...
...
cms/templates/js/transcripts/messages/transcripts-uploaded.underscore
View file @
68e1985d
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
<button class="action setting-upload" type="button" name="setting-upload" value="<%= gettext("Upload New Timed Transcript") %>" data-tooltip="<%= gettext("Upload New Timed Transcript") %>">
<button class="action setting-upload" type="button" name="setting-upload" value="<%= gettext("Upload New Timed Transcript") %>" data-tooltip="<%= gettext("Upload New Timed Transcript") %>">
<span><%= gettext("Upload New Timed Transcript") %></span>
<span><%= gettext("Upload New Timed Transcript") %></span>
</button>
</button>
<a class="action setting-download" href="/transcripts/download?locator=<%= component_locator %>" data-tooltip="<%= gettext("Download to Edit") %>">
<a class="action setting-download" href="/transcripts/download?locator=<%= component_locator %>
&subs_id=<%= subs_id %>
" data-tooltip="<%= gettext("Download to Edit") %>">
<span><%= gettext("Download to Edit") %></span>
<span><%= gettext("Download to Edit") %></span>
</a>
</a>
</div>
</div>
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