-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
base: master
Are you sure you want to change the base?
Conversation
...t_app/src/main/java/org/odk/collect/android/database/instances/InstanceDatabaseMigrator.java
Outdated
Show resolved
Hide resolved
4f8fd41
to
ecdf646
Compare
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.
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.
...t_app/src/main/java/org/odk/collect/android/database/instances/InstanceDatabaseMigrator.java
Outdated
Show resolved
Hide resolved
...t_app/src/main/java/org/odk/collect/android/database/instances/InstanceDatabaseMigrator.java
Outdated
Show resolved
Hide resolved
...t_app/src/main/java/org/odk/collect/android/database/instances/InstanceDatabaseMigrator.java
Outdated
Show resolved
Hide resolved
collect_app/src/test/java/org/odk/collect/android/database/DatabaseInstancesRepositoryTest.kt
Outdated
Show resolved
Hide resolved
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.
Loving all the new Kotlin here as well as the fact we're seeing some database integrity creeping into Collect!
@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! |
collect_app/src/main/java/org/odk/collect/android/instancemanagement/LocalInstancesUseCases.kt
Outdated
Show resolved
Hide resolved
collect_app/src/main/java/org/odk/collect/android/database/DatabaseObjectMapper.kt
Show resolved
Hide resolved
...t_app/src/main/java/org/odk/collect/android/database/instances/InstanceDatabaseMigrator.java
Outdated
Show resolved
Hide resolved
..._app/src/main/java/org/odk/collect/android/formlists/savedformlist/SavedFormListViewModel.kt
Show resolved
Hide resolved
collect_app/src/main/java/org/odk/collect/android/formmanagement/formmap/FormMapViewModel.kt
Show resolved
Hide resolved
fun Instance.showAsEditable(settingsProvider: SettingsProvider): Boolean { | ||
return isDraft() && settingsProvider.getProtectedSettings() | ||
.getBoolean(ProtectedProjectKeys.KEY_EDIT_SAVED) | ||
} | ||
|
||
fun Instance.userVisibleInstanceName( |
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.
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)") |
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.
@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?
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.
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.
collect_app/src/main/java/org/odk/collect/android/utilities/InstanceUploaderUtils.java
Show resolved
Hide resolved
156728d
to
27a46f0
Compare
8fe56e9
to
89dd1a6
Compare
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. |
...t_app/src/main/java/org/odk/collect/android/database/instances/InstanceDatabaseMigrator.java
Show resolved
Hide resolved
private void openEditedInstance(long dbId) { | ||
Intent intent = FormFillingIntentFactory.editFinalizedFormIntent(requireContext(), currentProjectId, dbId); | ||
startActivity(intent); | ||
requireActivity().getOnBackPressedDispatcher().onBackPressed(); |
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.
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 -> { |
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 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()) |
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.
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?
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. |
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. |
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. |
The same crash mentioned above occurs in this scenario:
In this case I haven't noticed the issue after sending a form (not finalizing). |
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? |
I think it's a different one, so I filed a new issue. But the fix might be common for both, we will see. |
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
callededit_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 existingLAST_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:
FormA
.FormA
and finalize(Edit 1)
.FormA (Edit 1)
and finalize (Edit 2)
.FormA (Edit 1)
andFormA (Edit 2)
.FormA (Edit 1)
. Whether the submission succeeds or fails, its status is updated tosubmitted
orsubmission_failed
, and so is itsLAST_STATUS_CHANGE_DATE
.FormA (Edit 1)
will now appear newer thanFormA (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:
./gradlew connectedAndroidTest
(or./gradlew testLab
) and confirmed all checks still passDateFormatsTest