Uh oh!
There was an error while loading. Please reload this page.
Sync unsaved changes before leaving - #2699
Conversation
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
Codecov Report
@@ Coverage Diff @@## develop #2699 +/- ##
========================================
Coverage 84.94% 84.94% ========================================
Files 301 301 Lines 15227 15227 ========================================
Hits 12934 12934 Misses 2293 2293 Continue to review full report at Codecov.
|
rtibbles
left a comment
There was a problem hiding this comment.
The logout flow seems to be mostly covered, but this might cause aborted sync requests in both the logout and non-logout navigating away from the page flows.
Uh oh!
There was an error while loading. Please reload this page.
| masteryModelNRequired: 'Required', | ||
| masteryModelNGtZero: 'Must be at least 1', | ||
| masteryModelNWholeNumber: 'Must be a whole number', | ||
| confirmLogout: 'Changes you made may not be saved. Are you sure you want to leave this page?', |
There was a problem hiding this comment.
Flagging that this won't be translated just yet.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This reverts commit 26bded0.
Otherwise Dexie Observable listeners ignore the table. Underscore seem to denote Dexie's internal tables.
Description
Inform users about unsaved changes and sync them before they leave the application.
Issue Addressed
Closes#2496
Steps to Test
SYNC_IF_NO_CHANGES_FOR, for example to 20 seconds, so you're able to leave the application comfortably in all possible ways/syncendpoint, for example add a topic to a channel in the channel editor or update a node in the edit modalImplementation Notes
This PR adds
SyncProgressPluginVuex plugin that updatesunsavedChangestotrue/falsebased on whether there are some unsaved changes in the IndexedDB table where changes for sync are kept. The value will be updated on each change of the table. The plugin is installed during an app initialization.Leaving by closing a window
During an app initialization,
beforeunloadhandler is defined. The handler runs server sync immediately and prevents unload if there are anyunsavedChangesby showing the default browser prompt to a user who can then decide if they really want to leave while still having some unsaved changes.Leaving by using logout function
When logging out, a custom confirmation dialog is displayed if there are any
unsavedChangesand server sync is triggered immediately. If user confirms that they want to leave, logout will be performed and additionally,logoutConfirmed:truewill be saved tosessionStorage.logoutConfirmedvalue is then checked inbeforeunloadhandler and if set totrue, the handler won't continue executing. This is to prevent from showing a confirmation dialog the second time in case a user has already confirmed that they want to leave.The main reason behind this implementation is that
beforeunloadevent handler has some limits to prevent developers from introducing malicious functionality. One of those limitations is that decision logic related to preventing unload needs to be synchronous. Because of that, it doesn't seem to be possible to reuse the solution fromSavingIndicator.Checklist
pages,components, andlayoutsdirectories as described in the docs?Design notes
Even though it was possible to specify a custom message in the past in
beforeunloadevent handler, most modern browsers have dropped support. Therefore a default browser message (can vary across browsers) will be displayed when leaving the app by closing a window. Because of that, the message that @jtamiacedesigned is used only in a prompt displayed after trying to log out in a regular way.Comments
I'd appreciate some thoughts on the following:
Saving indicator
I was thinking about connecting
SavingIndicatorused in edit modal toSyncProgressPlugininstead of polling IndexedDB though at this point,SavingIndicatoris implemented to check only for saving progress of nodes being edited whereasunsavedChangesis simply a Boolean value containing information about whether there are any unsaved changes from any part of the app.Possible solutions:
(1) Leave it as is
(2) Implement
SyncProgressPluginin a much more granular way to contain information about nodes etc.(3) Simplify
SavingIndicatorto check whether there are any unsaved changes by callingareAllChangesSavedgetter, not only those related to nodes being currently edited in the edit modal.I like consistency of (3) and it seems to make sense from UX point of view because with approaches (1) and (2), we could run into a situation when saving indicator would not visible but "Unsaved changes" prompt could be still displayed when trying to exit the app while having some unsaved changes related to nodes that are currently not being edited. Thoughts?
Navigation between apps
Due to our multiple apps architecture, the "Unsaved changes" prompt can be displayed when navigating between apps when there are unsaved changes which disrupts user experience. I increased
SYNC_IF_NO_CHANGES_FORto 20 seconds for the sake of testing this PR so you can check this for example by adding a new topic in a channel editor and navigating to/channelsURL shortly after that.There is no information on destination URL in
beforeunloadevent (again, to prevent from malicious use), so I am not sure how to solve it. I think there is no need to be worried about it because our default value forSYNC_IF_NO_CHANGES_FORis 2 seconds so it shouldn't happen very often and also it will be solved for free as soon as we migrate to using one app. Is it okay for now?