Skip to content

Conversation

josephmyers
Copy link
Collaborator

@josephmyers josephmyers commented Sep 25, 2025

Apparently, the Location object is not aware of navigation guards, where Router is. The Location object was popping off the top item on history immediately after clicking Cancel, even when the confirm prompt returned "stay on page." Changing to use Router fixes the issue.


This change is Reviewable

@josephmyers josephmyers added the will require testing PR should not be merged until testers confirm testing is complete label Sep 25, 2025
@josephmyers josephmyers marked this pull request as ready for review September 25, 2025 19:30
Copy link

codecov bot commented Sep 25, 2025

Codecov Report

❌ Patch coverage is 50.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.29%. Comparing base (3360c9c) to head (5155d32).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...n/draft-usfm-format/draft-usfm-format.component.ts 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3467      +/-   ##
==========================================
- Coverage   82.30%   82.29%   -0.01%     
==========================================
  Files         613      613              
  Lines       36857    36859       +2     
  Branches     6048     6025      -23     
==========================================
- Hits        30335    30334       -1     
- Misses       5643     5645       +2     
- Partials      879      880       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@Nateowami Nateowami left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion


src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts line 201 at r1 (raw file):

  async close(): Promise<void> {
    await this.router.navigate(['..'], { relativeTo: this.activatedRoute });

This works? In any context I've seen before, .. in a URL does not mean backward in a history, but goes up one level in a path hierarchy. So .. relative to /projects/68c0da61d10a6e37a0c5b7d4/draft-generation/format would be equivalent to removing /format from the end of the path. If this somehow works as a way to go back, I can't see how.

Copy link
Collaborator Author

@josephmyers josephmyers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 3 files reviewed, 1 unresolved discussion (waiting on @Nateowami)


src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts line 201 at r1 (raw file):

Previously, Nateowami wrote…

This works? In any context I've seen before, .. in a URL does not mean backward in a history, but goes up one level in a path hierarchy. So .. relative to /projects/68c0da61d10a6e37a0c5b7d4/draft-generation/format would be equivalent to removing /format from the end of the path. If this somehow works as a way to go back, I can't see how.

Big oops. Thanks for catching me on this. I had to solve it a different way. I'm wondering if that config change would impact anything else in the app?

Copy link
Collaborator

@Nateowami Nateowami left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 3 files reviewed, 1 unresolved discussion (waiting on @josephmyers)


src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts line 201 at r1 (raw file):

Previously, josephmyers wrote…

Big oops. Thanks for catching me on this. I had to solve it a different way. I'm wondering if that config change would impact anything else in the app?

In my opinion, the simplest solution is this:

cancelClicked(): void {
  if (this.changesHaveBeenMade && !(await this.confirmLeaveWithUnsavedChanges())) return;
  exitComponent();
}

exitComponent(): void {
  this.location.back();
}

The fact that the logic is explicit makes it so much easier to understand what is happening. There's also no concerns about how it might impact other components, or whether automated tests properly set up the routing environment to have a correct test. When it's in some other file it's extremely difficult for a developer who's unaware it exists (it confused me when I was trying to figure out what was going on). Or at the very least the DraftNavigationAuthGuard could be moved to this file.

Copy link
Collaborator Author

@josephmyers josephmyers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 3 files reviewed, 1 unresolved discussion (waiting on @Nateowami)


src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts line 201 at r1 (raw file):

Previously, Nateowami wrote…

In my opinion, the simplest solution is this:

cancelClicked(): void {
  if (this.changesHaveBeenMade && !(await this.confirmLeaveWithUnsavedChanges())) return;
  exitComponent();
}

exitComponent(): void {
  this.location.back();
}

The fact that the logic is explicit makes it so much easier to understand what is happening. There's also no concerns about how it might impact other components, or whether automated tests properly set up the routing environment to have a correct test. When it's in some other file it's extremely difficult for a developer who's unaware it exists (it confused me when I was trying to figure out what was going on). Or at the very least the DraftNavigationAuthGuard could be moved to this file.

I may be misunderstanding your full solution, but this only partially works, since it just fixes the bug when using Cancel. If you use the Back button, you can still break things following the test steps. I'm not sure how to get your solution to work with Back.

@Nateowami
Copy link
Collaborator

@josephmyers I wasn't considering the back button, but even considering it, I don't think we really need to care if the back button lets a user leave with unsaved changes.

@josephmyers
Copy link
Collaborator Author

Okay, so just confirming you're good with having the Back button bugged? I've pushed your solution

@Nateowami
Copy link
Collaborator

What do you mean by "bugged"? Do you mean simply that it won't open a confirmation dialog? I wouldn't consider that a bug.

@josephmyers
Copy link
Collaborator Author

It's bugged in the same way that Cancel is bugged (on master). On master, Cancel and Back behave the same way, and this bugfix fixes the issue for Cancel only. (The real bug is with how the browser's Back functionality works with the navigation guard and the browser history.)

Apparently, the Location object is not aware of navigation guards, where Router is. The Location object was popping off the top item on history immediately after clicking Cancel, even when the confirm prompt returned "stay on page." Changing to use Router fixes the issue.
This change makes navigation for canceled navigation attempts, like CanDeactivate, navigate the opposite direction, instead of replacing the item in the history. Replacing the item in the history was corrupting the history when using location.back() and then canceling. I'm actually not sure why you would want to be messing with the history in the first place. 'computed' seems like the sensible option. If the user hits back, then cancels, the router cancels by going forward.
This solution does not fix the problem when using the Back button. Maybe we don't care?
@Nateowami
Copy link
Collaborator

The changes look a lot better now, but the confirmation dialog now appears twice when the cancel button is used.

As an aside, I don't think that my proposed solution would leave the back button with the behavior on master. My suggestion is/was:

  • Remove all deactivate guards
  • When user clicks back, allow the browser to send the user back
  • When user clicks cancel, if changes have been made, open confirmation dialog, and depending on selection, go back

To me that seemed the simplest. I think you may be close to a simple-ish solution that confirms upon use of the back button as well, so don't feel like you have to go down the route I was proposing, but I'm leaving the explanation here for the sake of clarifying what I was suggesting.

@Nateowami Nateowami self-assigned this Oct 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
will require testing PR should not be merged until testers confirm testing is complete
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants