SF-3835 Do not allow uploading training data when offline#3985
SF-3835 Do not allow uploading training data when offline#3985pmachapman wants to merge 2 commits into
Conversation
|
📸 Screenshot diff deployed! (1 change) View the visual diff at: https://pr-3985--sf-screenshot-diffs.netlify.app |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3985 +/- ##
=======================================
Coverage 81.03% 81.04%
=======================================
Files 645 645
Lines 41531 41541 +10
Branches 6743 6745 +2
=======================================
+ Hits 33656 33668 +12
+ Misses 6773 6771 -2
Partials 1102 1102 ☔ View full report in Codecov by Harness. |
Nateowami
left a comment
There was a problem hiding this comment.
Rather than changing the error message, I took the same approach as the chapter audio dialog and disabled uploading when offline
The problem is: All errors when uploading a file (regardless of cause; they could be network related, bad file, or something else) are attributed to a malformed file, and the user is shown this message:
Your file needs to have two columns, and every row must have a value in both columns. Please fill in any empty cells and try again.
The error message should be shown only when a specific error code (could be HTTP status code, or something returned via JSONRPC) indicates a problem with the file, and the error message should contemplate the same breadth of potential problem as the code that triggers it (for example, I don't know what happens when you upload an unsupported file type, but if it can trigger the message, then the message should specify to check that the file type is one of the supported types). Disabling upload when we know we're offline doesn't stop network errors from occurring; it only reduces their frequency.
Also, we generally avoid disabling buttons, except when a feature is unavailable due to the user being offline, and then only disabling them in the context where we would show a message saying the user is offline. So in general it would be better to let the user open the upload dialog, but show a message about the user being offline inside the dialog.
@Nateowami made 1 comment.
Reviewable status: 0 of 7 files reviewed, all discussions resolved.
pmachapman
left a comment
There was a problem hiding this comment.
The error message should be shown only when a specific error code (could be HTTP status code, or something returned via JSONRPC) indicates a problem with the file, and the error message should contemplate the same breadth of potential problem as the code that triggers it (for example, I don't know what happens when you upload an unsupported file type, but if it can trigger the message, then the message should specify to check that the file type is one of the supported types). Disabling upload when we know we're offline doesn't stop network errors from occurring; it only reduces their frequency.
I have updated this PR to catch offline and format errors, and display an appropriate error message. I tried to do it in a way that would not break the other code dependent on the upload returning undefined on error.
Also, we generally avoid disabling buttons, except when a feature is unavailable due to the user being offline, and then only disabling them in the context where we would show a message saying the user is offline. So in general it would be better to let the user open the upload dialog, but show a message about the user being offline inside the dialog.
I agree. I made it offline because all the rest of the form cannot be used if offline, and most of the form was already disabled if offline - uploading the training sources offline, then connecting to click submit seems like an odd user workflow. If connectivity is interrupted during upload, then an offline error will be displayed.
@pmachapman made 1 comment.
Reviewable status: 0 of 12 files reviewed, all discussions resolved (waiting on Nateowami).
Nateowami
left a comment
There was a problem hiding this comment.
@Nateowami made 1 comment.
Reviewable status: 0 of 12 files reviewed, 1 unresolved discussion (waiting on pmachapman).
src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.ts line 129 at r2 (raw file):
* @param returnUndefinedForErrors If true, errors will be rethrown and undefined will only be returned if offline. */ async onlineUploadFileOrFail(
Wouldn't the canonical way to do this be to have onlineUploadFile and tryOnlineUploadFile (the latter of which wraps the former in try/catch)?
The current method signature creates code that does not make clear what is happening:
const audioUrl: string | undefined = await this.fileService.onlineUploadFileOrFail(
FileType.Audio,
this.data.projectId, // can't verify that this arg is in the correct position and didn't get swapped with another string arg
TextAudioDoc.COLLECTION, // can't verify that this arg is in the correct position and didn't get swapped with another string arg
objectId(), // can't verify that this arg is in the correct position and didn't get swapped with another string arg
this.audio!.blob!, // probably correct position since it's a Blob so it would fail type check if it were in wrong position
this.audio!.fileName!, // can't verify that this arg is in the correct position and didn't get swapped with another string arg
true, // no idea what this is for unless I look up method
true // no idea what this is for unless I look up method
);
pmachapman
left a comment
There was a problem hiding this comment.
@pmachapman made 1 comment.
Reviewable status: 0 of 12 files reviewed, 1 unresolved discussion (waiting on Nateowami).
src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.ts line 129 at r2 (raw file):
Previously, Nateowami wrote…
Wouldn't the canonical way to do this be to have onlineUploadFile and tryOnlineUploadFile (the latter of which wraps the former in try/catch)?
The current method signature creates code that does not make clear what is happening:
const audioUrl: string | undefined = await this.fileService.onlineUploadFileOrFail( FileType.Audio, this.data.projectId, // can't verify that this arg is in the correct position and didn't get swapped with another string arg TextAudioDoc.COLLECTION, // can't verify that this arg is in the correct position and didn't get swapped with another string arg objectId(), // can't verify that this arg is in the correct position and didn't get swapped with another string arg this.audio!.blob!, // probably correct position since it's a Blob so it would fail type check if it were in wrong position this.audio!.fileName!, // can't verify that this arg is in the correct position and didn't get swapped with another string arg true, // no idea what this is for unless I look up method true // no idea what this is for unless I look up method );
Done. Thank you!
Nateowami
left a comment
There was a problem hiding this comment.
@Nateowami reviewed 8 files and all commit messages, and made 3 comments.
Reviewable status: 8 of 12 files reviewed, 3 unresolved discussions (waiting on pmachapman).
src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.ts line 129 at r2 (raw file):
Previously, pmachapman (Peter Chapman) wrote…
Done. Thank you!
Thanks for fixing this. Seems like "or fail" doesn't belong in the method name since it no longer swallows errors.
src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/training-data/training-data-multi-select.component.ts line 70 at r3 (raw file):
openUploadDialog(): void { if (this.activatedProjectService.projectId == null) return; if (!this.appOnline) return;
Isn't this the wrong place for a check like this? Seems like the caller should be doing the check. Or alternatively the dialog should open and say it's not available offline. Doing nothing doesn't seem like the correct approach.
src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.ts line 145 at r3 (raw file):
} catch {} } return undefined;
I really don't think defining undefined as meaning offline is good practice. It's a value you have to remember to check for, it's not obvious what it means, and it's the value that is most likely to accidentally pop up in this language, meaning findOrUpdateCache mistakenly returning undefined would not be improbable. If we want to create a value to check for instead of an exception, a string (that the type system is aware of) would not pop up accidentally, and would be obvious what it means.
That said, I really don't think this method should be checking if we're online at all. Network conditions are inherently unpredictable, and therefore we can't use guards to completely prevent requests that will fail for network reasons. Therefore I think it makes most sense to put such guards at the UI level (e.g. disabled buttons with explanatory text), and not have business logic methods named doThing that really mean doThingButOnlyUnderCertainCircumstances, and to consider such guards nice-to-have, not absolute requirements.
Rather than changing the error message, I took the same approach as the chapter audio dialog and disabled uploading when offline
This change is