-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anton/store video progress #2365
Conversation
@@ -193,7 +193,7 @@ def to_json(self, value): | |||
if not value: | |||
return "00:00:00" | |||
|
|||
if isinstance(value, float): # backward compatibility | |||
if isinstance(value, float) or isinstance(value, int): # backward compatibility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isinstance(value, (float, int))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davestgermain You are right! Python docs on isinstance reveals that the second argument can indeed be a tuple of type objects
. Thx!
@@ -193,7 +193,7 @@ def to_json(self, value): | |||
if not value: | |||
return "00:00:00" | |||
|
|||
if isinstance(value, float): # backward compatibility | |||
if isinstance(value, (float, int)): # backward compatibility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add test.
@polesye You wrote that I should add tests for https://github.com/edx/edx-platform/pull/2365#discussion-diff-9415398R196 . After working with @auraz , we came up with a solution where the change:
is no longer necessary. Please see edx/edx-platform@a2e1e22 . |
seconds = seconds % 60 | ||
minutes = minutes % 60 | ||
|
||
"#{pad(hours)}:#{pad(minutes)}:#{pad(seconds % 60)}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this function used only when we send data to server and its result is not user facing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye Yes. This function was added for the purpose of sending the correctly formatted time string to the server. I decided to add it here in the hope that in the future it might be useful in other places. Code reuse!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ask it, because if result of this function is planned to be visible for users, a11y should be added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye It will not be user-facing. So no need for internationalization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave comment about that.
@valera-rozuvan Did you write js unit tests? |
@@ -8,6 +8,8 @@ | |||
|
|||
afterEach(function () { | |||
$('source').remove(); | |||
window['VideoState'] = {}; | |||
window['VideoState']['id'] = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistic nitpick: In Javascript a.b
and a['b']
are identical. I prefer the former when you're dealing with static strings. Can you change these lines to:
window.VideoState = {};
window.VideoState.id = {};
👍 |
@polesye No. I did not write JavaScript unit tests. |
Please add tests for |
And I'm waiting for acceptance tests. |
data.position = Math.round(data.position); | ||
this.storage.setItem('position', data.position, true); | ||
|
||
data.position = Time.formatFull(data.position); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need round value just when send position to the server.
this.storage.setItem('position', data.position, true);
data.position = Time.formatFull(data.position);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye If the server stores the time as a HH:MM:SS value, and writes position into the data-position attribute of the HTML template as an integer, why do we need to preserve the decimal point on the user's PC? I think it is better to have it rounded before we store using the storage class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@valera-rozuvan No matter how do we store this value on user's PC (It's just a property of global object, not a cookie), so I don't see a reason to make this redundant rounding. Time.formatFull
uses Math.floor
under the hood.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye Done.
@polesye I have implemented acceptance test to check that position in video is stored on page refresh. All tests pass. All comments by you and @singingwolfboy have been addressed. Please list what other tests I have to implement so that @Lyla-Fischer understands how much work on this PR is left to be done. |
# length of the video. Right now "0:10 / 1:55", and "0:11 / 1:55" are | ||
# hard coded, so the test will break if the default video will be | ||
# changed. | ||
world.wait_for(lambda _: world.css_html('.vidtime')[:4] == '0:10' or world.css_html('.vidtime')[:4] == '0:11') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe, that even if you break js method seekTo
, this condition will be passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye I have tried this. I am aware that you can use {}
and .format()
methods. However, the test fails when you do this. Please check for yourself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you had an issues with curly braces.
Format strings contain “replacement fields” surrounded by curly braces {}. Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }}.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye You were right = ) Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye The condition will not be passed. This is because world.wait_for()
has a default wait time of 5 seconds. If we are waiting for 10 seconds of video to play, the test will fail before it gets to 10 seconds, because it will timeout after 5 seconds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@polesye So the only way this test will pass if the video starts playing from the 10th second.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I suggest to set timeout
explicitly, because default value can be changed. And I think world.wait_for(lambda _: world.css_html('.vidtime')[:4] == '0:11')
will be enough.
@polesye I have added another acceptance test. How many more should I add? |
@valera-rozuvan 2 tests that cover following behaviors:
|
@polesye I have added the 2 tests you requested, and also addressed your comment
What else? |
@polesye I have simplified |
I should check it manually. |
@@ -215,7 +215,7 @@ | |||
} | |||
|
|||
$.each(attrs, function (name, value) { | |||
return result = result && element.attr(name) === value; | |||
result = result && element.attr(name) === value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like rather this code could be improved by using _.every
:
toHaveAttrs: function(attrs) {
if ($.isEmptyObject(attrs)) {
return false;
}
var element = this.actual;
return _.every(attrs, function(value, name) {
return element.attr(name) === value;
});
I found that it doesn't store position sometimes (especially when you're reloading the page without pausing the video). I think that will be less confusing for users to show them an actual position (in vcr and progress slider position), before the video starts playing. But it shouldn't be a blocker for this PR and could be done in separate PR. |
|
||
return result; | ||
return _.every(attrs, function (value, name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@singingwolfboy Done.
if key == 'position' or key == u'position': | ||
relative_position = RelativeTime.isotime_to_timedelta(data[key]) | ||
# setattr(self, key, relative_position) | ||
self.position = relative_position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@singingwolfboy There is a bug in this line. It does not save to actual database. When the browser closes, and you open the browser again, the value of position is once again the default 0. What should I do to update the position value in the database?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why it wouldn't save to the database. Are you sure there's no exception being thrown? @cpennington any clues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nedbat What query should I run in mongo shell in order to absolutely be sure that the position
is 0. I want to run it when the browser is open, see that it is in fact 0, then trigger the saving of new position
via AJAX request to handle_ajax()
, and then check once again that the database has position
set to 0.
@auraz and @polesye I have visually confirmed using the Robomongo tool that position is not being stored in the database. Please look in the following JSON representing the 2 entries in the DB that are modified when I work with the Video:
You can see that @cpennington , @singingwolfboy , @nedbat Please help! |
@nedbat , @cpennington , @singingwolfboy Maybe it has something to do with how
|
The |
@cpennington , @singingwolfboy , @nedbat , @auraz , @polesye I have fixed the bug with |
@polesye Please finish with your review. |
👍 |
Student logins to edx, plays video, selects position, closes browser, opens video, position is restored. BLD-385
Anton/store video progress
* Correctly format date block dates. (cherry picked from commit 22cb307) * ECOM-3673 Update the course end date description text to remove the reference to certificate when course enrollment is in audit mode (cherry picked from commit 649e8b1) * Fixes for courseware date formatting/translation. (cherry picked from commit 80bfa36) Conflicts: lms/djangoapps/courseware/date_summary.py * Fix date summaries with Unicode format issues. This issue would show up when date formatting strings are translated with Unicode characters (like when testing with fake Esperanto translations). (cherry picked from commit c1a59cc) * Converts the dates on the dashboard, sidebar navigation, and important course dates to user specified time zone. (cherry picked from commit 0bf8fc4) Conflicts: common/djangoapps/util/date_utils.py common/lib/xmodule/xmodule/course_module.py common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py lms/djangoapps/ccx/tests/test_models.py lms/djangoapps/courseware/views/index.py lms/djangoapps/student_account/views.py lms/templates/dashboard/_dashboard_course_listing.html openedx/core/djangoapps/content/course_overviews/models.py openedx/core/djangoapps/user_api/preferences/api.py openedx/core/djangoapps/user_api/preferences/tests/test_views.py * Display JST for survey's answer datetime. openedx#2146 * Display JST for section's deadline and course start/end datetime. openedx#2146 * Display JST for face-to-face start/end datetime on Django Admin. openedx#2146 * Display JST for ORA2 settings. openedx#2146 * Add the validation of the schedule dates before 1900 openedx#2284 (openedx#2298) * Implements command count_initial_registration_course openedx#2221 (openedx#2296) * Add GaCourseEditorRole and GaLmsCourseStaffRole openedx#2150 (openedx#2306) * Add GaCourseEditorRole and GaLmsCourseStaffRole openedx#2150 * Add UT for studio openedx#2150 * Fix GaCourseEditor has access to after the course closed openedx#2150 * GaLmsCourseStaff can use the same function as the course staff at the staff debug info openedx#2150 * Fix UT and Bok choy openedx#2150 * Remove extra line feed openedx#2150 * Fix comment openedx#2150 * Mod conditions openedx#2150 * Move judgment conditions to template openedx#2150 * Fix comment openedx#2150 * Remove unused code openedx#2150 * Mod conditions for GaCourseEditor but a global staff openedx#2150 * Revert parameter CourseDetails.update_from_json openedx#2150 * Mod check for staff acccess at LMS for GaCourseEditor openedx#2150 * Rename GaCourseEditorRole -> GaGlobalCourseCreatorRole openedx#2150 * Rename GA_COURSE_EDITOR_USER_INFO -> GA_GLOBAL_COURSE_CREATOR_USER_INFO openedx#2150 * Rename GA_ACCESS_CHECK_TYPE_COURSE_EDITOR -> GA_ACCESS_CHECK_TYPE_GLOBAL_COURSE_CREATOR openedx#2150 * Rename Ga_Course_Editor -> Ga_Global_Course_Creator openedx#2150 * Rename gacourseeditor -> gaglobalcoursecreator openedx#2150 * Rename GaCourseEditor -> GaGlobalCourseCreator openedx#2150 * Rename course_editor -> global_course_creator openedx#2150 * Mod hide staff debug info for GaGlobalCourseCreatorRole openedx#2150 * Fix UT for GaGlobalCourseCreator openedx#2150 * Rename UT openedx#2150 * Fix skipped UT openedx#2150 * Remove unused code openedx#2150 * Fix argument openedx#2150 * Remove unused code openedx#2150 * Fix ambiguous conditions openedx#2150 * Rename GaLmsCourseStaffRole -> GaCourseScorerRole openedx#2150 * Rename GA_LMS_COURSE_STAFF_USER_INFO -> GA_COURSE_SCORER_USER_INFO openedx#2150 * Ga_Lms_Course_Staff -> Ga_Course_Scorer openedx#2150 * Rename galmscoursestaff -> gacoursescorer openedx#2150 * Rename GaLmsCourseStaff -> GaCourseScorer openedx#2150 * Rename lms_course_staff -> course_scorer openedx#2150 * Fix translation openedx#2150 * Fix comment openedx#2150 * Add personal info mask at resign openedx#2148 (openedx#2316) * Add personal info mask at unenroll openedx#2148 * Fix Review. * Add Unit Test. * Add JST date fields near UTC date fields. openedx#2230 (openedx#2307) * Add JST date fields near UTC date fields. openedx#2230 * Fix Review * Fix Review 2. * Add yml Files * Add option of progress restriction that makes users need to pass prob… (openedx#2305) * Add option of progress restriction that makes users need to pass problems. openedx#2147 * Skip Bok-Choy CoursewareProgressRestrictionTest temporarily because this may cause an error of other test * Fix review 1 openedx#2147 * Fix review 2 openedx#2147 * Fix to use different username and email from test_ga_register.py so that no error occurs on test_register_and_activate. openedx#2147 * Fix review 3 openedx#2147 * Fix review 4 openedx#2147 * Fix review 5-1 * Fix review 5-2 * Fix review 5-3 * Fix review 5-4 * Fix review 5-5 * Fix review 5-6 * Fix review 5-7 * Fix review 5-8 * Fix review 5-9 * Fix review 5-10 * Fix review 5-12 * Fix review 5-14 revert 5-13 * Fix review 5-15 * Fix review 5-16 * Fix review 6-1 openedx#2147 * Fix review 6-2 openedx#2147 * Fix review 6-3 openedx#2147 * Fix UTC message in survey page. openedx#2340 (openedx#2345) * Fix bug for manage_user_standing page. openedx#2347 (openedx#2348) * Fix bug and add failed testcase for mask_resigned_user command. openedx#2362 (openedx#2365) * Add confirm for account_disabled of manage_user_standing openedx#2366 (openedx#2367)
persist student progress in video
The following test cases are achieved with this PR:
JIRA issue
BLD-385
Reviewers