8000 Improve editing finalized forms by grzesiek2010 · Pull Request #6698 · getodk/collect · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Improve editing finalized forms #6698

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

Open
wants to merge 29 commits into
base: master
Choose a base branch
from

Conversation

grzesiek2010
Copy link
Member
@grzesiek2010 grzesiek2010 commented Apr 22, 2025

Closes #6688
Closes #6593
Closes #6594
Closes #6689
Closes #6686

Why is this the best possible solution? Were any other approaches considered?

#6688
I've decided to add a new column to instances.db called edit_of. This column will indicate whether a form is an edit of a finalized form, and if so, store the ID of the original form. This change will help address #6594. With this column, I'll be able to identify the latest edit and determine the sequence of edits for any given form. This seems to be everything I will need.

#6593
What initially seemed like a simple task turned out to be more complex than expected. As I mentioned earlier, I thought that the new edit_of column introduced for #6688, together with the existing LAST_STATUS_CHANGE_DATE, would be sufficient to address issues #6593 and #6594. Unfortunately, that assumption was incorrect.

I initially believed that LAST_STATUS_CHANGE_DATE could be used to sort edits and determine both the most recent edit and the sequence number of each edit. However, LAST_STATUS_CHANGE_DATE is updated every time an instance is modified in the database (even for status changes and rightly so). This makes it unreliable for determining the order of edits.

To illustrate the problem, consider the following scenario:

  1. Finalize FormA.
  2. Edit FormA and finalize (Edit 1).
  3. Edit FormA (Edit 1) and finalize (Edit 2).
  4. At this point, we correctly have FormA (Edit 1) and FormA (Edit 2).
  5. Now try to send FormA (Edit 1). Whether the submission succeeds or fails, its status is updated to submitted or submission_failed, and so is its LAST_STATUS_CHANGE_DATE.
  6. As a result, FormA (Edit 1) will now appear newer than FormA (Edit 2), even though it was created earlier.

To address this, I introduced a new column: editNumber. This allows us to store a fixed sequence number for each edit that doesn’t change, ensuring we can accurately determine the order of edits and identify the latest one.

#6594
As previously mentioned, the editNumber column is essential for correctly determining the order of edits. There's nothing more to discuss on this point.

#6689
Nothing important to discuss here - I just fixed how we observe the process of editing a finalized instance.

#6686
Nothing to discuss here.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

#6688
This should only prevent the creation or updating of entities when editing a finalized form. However, since the implementation involves changes to the database structure, which can always be tricky, we need to test the upgrade process from an older version to the one introduced in this pull request.
#6593
This change also modifies the database structure, so the upgrade process should be tested as well - something that can conveniently be done in one go since both changes are included in the same pull request.
#6594
Here, it is important to make sure that users are always prompted to open the newest edit no mater how many of them are.
#6689
Here, we can just make sure the issue is no longer visible by reproducing it.
#6686
Please be careful when testing this, as there are many combinations to consider: both "Save as Draft" and "Finalize/Send" buttons visible or only one of them, editing finalized forms enabled or not... It can be confusing. Please make sure that all texts make sense.

Do we need any specific form for testing your changes? If so, please attach one.

#6688
Any form that registers/updates entities + is editable (client-editable="true"). I've added two such forms for testis: fcf6926.
#6593 #6594 #6689
Any form that is editable (client-editable="true").
#6686
Both forms that can't be edited after finalization and those that can be edited.

Does this change require updates to documentation? If so, please file an issue here and include the link below.

Yes: getodk/docs#1941

Before submitting this PR, please make sure you have:

  • added or modified tests for any new or changed behavior
  • run ./gradlew connectedAndroidTest (or ./gradlew testLab) and confirmed all checks still pass
  • added a comment above any new strings describing it for translators
  • added any new strings with date formatting to DateFormatsTest
  • verified that any code or assets from external sources are properly credited in comments and/or in the about file.
  • verified that any new UI elements use theme colors. UI Components Style guidelines

@grzesiek2010 grzesiek2010 marked this pull request as ready for review April 22, 2025 21:05
@grzesiek2010 grzesiek2010 requested a review from seadowg April 22, 2025 21:05
Copy link
Member
@seadowg seadowg left a comment

Choose a reason for hiding this comment

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

It would be good to add a test that checks that an exception is thrown if you try and save an Instance an editOf with a bogus ID to ensure the foreign key.

@grzesiek2010 grzesiek2010 requested a review from seadowg April 23, 2025 20:08
@grzesiek2010 grzesiek2010 requested a review from seadowg April 24, 2025 11:36
Copy link
Member
@seadowg seadowg left a comment

Choose a reason for hiding this comment

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

@grzesiek2010 grzesiek2010 requested a review from seadowg April 24, 2025 12:55
Copy link
Member
@seadowg seadowg left a comment

Choose a reason for hiding this comment

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

Loving all the new Kotlin here as well as the fact we're seeing some database integrity creeping into Collect!

@seadowg
Copy link
Member
seadowg commented Apr 24, 2025

@grzesiek2010 I'll leave this unmerged for now seeing as it has migrations, and it'd be annoying to have to unwind them if QA finds something we didn't think of!

@grzesiek2010 grzesiek2010 changed the title Don't create/update entities when editing a finalized form + Highlight edited submissions Don't create/update entities when editing a finalized form + Highlight edited submissions + Block editing out of date submissions Apr 26, 2025
fun Instance.showAsEditable(settingsProvider: SettingsProvider): Boolean {
return isDraft() && settingsProvider.getProtectedSettings()
.getBoolean(ProtectedProjectKeys.KEY_EDIT_SAVED)
}

fun Instance.userVisibleInstanceName(
Copy link
Member

Choose a reason for hiding this comment

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

Agreed! I think it makes a lot more sense for this to be a "display" concern rather than data we store. I'm now wondering if we could also use this method to handle the case where there's no instance name and stop saving the form name instead?

@@ -114,7 +114,7 @@ class EditSavedFormTest {
.editForm("One Question Editable")
.clickOnQuestion("what is your age")
.answerQuestion("what is your age", "456")
.swipeToEndScreen()
.swipeToEndScreen("One Question Editable (Edit 1)")
Copy link
Member

Choose a reason for hiding this comment

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

@alyblenkin so this PR also makes the form entry end screen show the "(Edit x)" suffix on the instance name. Do we want that or should that only show in form lists?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry I missed this! We touched on this a little this morning, but I think if we can show the instance name that would be great.

@grzesiek2010
Copy link
Member Author

@seadowg there are new changes for #6689 and #6686

@grzesiek2010 grzesiek2010 changed the title Don't create/update entities when editing a finalized form + Highlight edited submissions + Block editing out of date submissions Don't create/update entities when editing a finalized form + Highlight edited submissions + Block editing out of date submissions + Rotating while setting up edit creates duplicate instance + Change end of form message when edits are enabled Apr 29, 2025
@grzesiek2010 grzesiek2010 requested a review from seadowg April 29, 2025 00:11
@seadowg
Copy link
Member
seadowg commented Apr 29, 2025

@seadowg there are new changes for #6689 and #6686

Got ya! Let's limit to this set of changes, so things don't get confusing. I think all the DB changes you had planned are no in, and I don't see why we can't merge while we're waiting for Central to fix the bug with updates as long as everything on our side looks good. I'm just going to update the PR title as well as the changes are all linked.

@seadowg seadowg changed the title Don't create/update entities when editing a finalized form + Highlight edited submissions + Block editing out of date submissions + Rotating while setting up edit creates duplicate instance + Change end of form message when edits are enabled Improve editing finalized forms Apr 29, 2025
private void openEditedInstance(long dbId) {
Intent intent = FormFillingIntentFactory.editFinalizedFormIntent(requireContext(), currentProjectId, dbId);
startActivity(intent);
requireActivity().getOnBackPressedDispatcher().onBackPressed();
Copy link
Member

Choose a reason for hiding this comment

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

While we're here: should the set-up for the OnBackPressedCallback callback be in onAttach rather than onViewCreated?

@@ -106,7 +111,13 @@ public void onAttach(@NonNull Context context) {
requireActivity().setTitle(formEntryViewModel.getFormController().getFormTitle());
startIndex = formEntryViewModel.getFormController().getFormIndex();

MaterialProgressDialogFragment.showOn(this, formHierarchyViewModel.isCloning(), getParentFragmentManager(), () -> {
formHierarchyViewModel.getInstanceEditResult().observe(this, instanceEditResult -> {
Copy link
Member

Choose a reason for hiding this comment

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

I think there's still going to be a problem here if the user navigates away from Collect and back again while cloning and the Activity gets recreated (clearing view model state). I'm going to test that and update #6691 though, as I think the new cases protecting old edits will handle a lot of this.

Locale.getDefault()
).format(instance.getLastStatusChangeDate());

new MaterialAlertDialogBuilder(requireContext())
Copy link
Member

Choose a reason for hiding this comment

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

It'd definitely help us down the line to convert FormHierarchyFragmentHostActivity to using a nav graph and then have the dialogs here just be DialogFragment implementations that are navigated to with the NavigationController. This is something we'll want to do anyway if we want form entry/hierarchy to be one Activity using a nav graph. Is that something you'd be up for trying out as a follow-up?

@dbemke
Copy link
dbemke commented May 5, 2025

What is the expected result in this case on Central (how many submissions: 2 submissions or 1 submission with edits)?

  1. Send a editable form.
  2. Go to "Sent" and start editing the form.
  3. Discard the changes.
  4. Go to "Ready to send" and finalize all drafts.
  5. Go to Central and check the submissions (example submission 4, 5 in https://staging.getodk.cloud/projects/152/forms/all-widgets/submissions)

@grzesiek2010
Copy link
Member Author

What is the expected result in this case on Central (how many submissions: 2 submissions or 1 submission with edits)?

There should be 1 submission with one edit. Once you click the edit icon the edit is created so even if you discard changes it is still there. When all drafts are finalized and sent it should be there.

@dbemke
Copy link
dbemke commented May 6, 2025

There should be 1 submission with one edit. Once you click the edit icon the edit is created so even if you discard changes it is still there. When all drafts are finalized and sent it should be there.

To summarize our call and discussion on this issue and not to lose information (while I'm testing Central) in this case there are 2 separate submission.

@grzesiek2010
Copy link
Member Author

To summarize our call and discussion on this issue and not to lose information (while I'm testing Central) in this case there are 2 separate submission.

I'm going to try to reproduce this and understand what happens.

@dbemke
Copy link
dbemke commented May 6, 2025

I'm going to try to reproduce this and understand what happens.

I just tried a few times and it seems that bulk finalizing might cause 2 submissions- if I open a draft (discarded from edit finalized) and finalize then I get 1 submission as expected.

@dbemke
Copy link
dbemke commented May 7, 2025

Crash after trying to delete a form which has edits and is with "sending failed" status. The issue doesn't occur on the master version. The issue also doesn't occur in forms which aren't editable.
crashonOrygWithEditFin

Steps to reproduce:

  1. Download a project with a form which is editable.
  2. Send a submission.
  3. Go to "Sent" and edit the form.
  4. Go to "Ready to send" , tap the three dots, "Change View" and select "Show Sent and Unsent Forms".
  5. Select the first version of the form (not the edit) and try to send it (it gets "sending failed" status).
  6. Go to "Delete form" and try to delete the form with "sending failed" status.

@dbemke
Copy link
dbemke commented May 7, 2025

The same crash mentioned above occurs in this scenario:

  1. Download a project with an editable form.
  2. Set auto send to "off".
  3. Finalize a form.
  4. Go to "Ready to send" and edit the form and finalize it.
  5. Go to "Delete form" and select both forms and try to delete them.

In this case I haven't noticed the issue after sending a form (not finalizing).

@seadowg
Copy link
Member
seadowg commented May 7, 2025

@dbemke both these cases should be fixed by #6703. I'd expect both cases where you delete a form that has edits to cause crashes at the moment.

@grzesiek2010
Copy link
Member Author

I just tried a few times and it seems that bulk finalizing might cause 2 submissions- if I open a draft (discarded from edit finalized) and finalize then I get 1 submission as expected.

It removes deprecatedId, which indicates it is an edit. The same happens on master, so it shouldn't block you. I'm going to file a separate issue and fix it.

@seadowg
Copy link
Member
seadowg commented May 8, 2025

It removes deprecatedId, which indicates it is an edit. The same happens on master, so it shouldn't block you. I'm going to file a separate issue and fix it.

Should this case maybe get added to #6691, or is it a different problem?

@grzesiek2010
Copy link
Member Author

Should this case maybe get added to #6691, or is it a different problem?

I think it's a different one, so I filed a new issue. But the fix might be common for both, we will see.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
0