Skip to content

Commit

Permalink
Merge pull request #5728 from seadowg/remove-grade-period
Browse files Browse the repository at this point in the history
Remove grace period for v2023.3
  • Loading branch information
grzesiek2010 authored Sep 12, 2023
2 parents f02d949 + 5606fac commit ee49671
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.odk.collect.android.support.pages.FormEntryPage;
import org.odk.collect.android.support.pages.MainMenuPage;
import org.odk.collect.android.support.pages.SaveOrDiscardFormDialog;
import org.odk.collect.android.support.pages.SendFinalizedFormPage;
import org.odk.collect.android.support.rules.CollectTestRule;
import org.odk.collect.android.support.rules.TestRuleChain;
import org.odk.collect.audiorecorder.recording.AudioRecorder;
Expand Down Expand Up @@ -176,10 +177,16 @@ public void whenRecordAudioPermissionNotGranted_openingForm_andDenyingPermission
@Test
public void viewForm_doesNotRecordAudio() {
rule.startAtMainMenu()
.setServer(testDependencies.server.getURL())
.copyForm("one-question-background-audio.xml")
.startBlankForm("One Question")
.fillOutAndFinalize(new FormEntryPage.QuestionAndAnswer("what is your age", "17"))
.clickSendFinalizedForm(1)
.clickSelectAll()
.clickSendSelected()
.clickOK(new SendFinalizedFormPage())
.pressBack(new MainMenuPage())
.clickViewSentForm(1)
.clickOnForm("One Question");

assertThat(stubAudioRecorderViewModel.isRecording(), is(false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.odk.collect.android.feature.formentry
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.odk.collect.android.R
import org.odk.collect.android.support.pages.MainMenuPage
import org.odk.collect.android.support.rules.CollectTestRule
import org.odk.collect.android.support.rules.TestRuleChain
Expand All @@ -30,7 +29,7 @@ class FormSavedSnackbarTest {
}

@Test
fun whenDraftFinalized_displaySnackbarWithViewAction() {
fun whenDraftFinalized_displaySnackbarWithViewActionThatOpensFormForEdit() {
rule.startAtMainMenu()
.copyForm("one-question.xml")
.startBlankForm("One Question")
Expand All @@ -43,10 +42,10 @@ class FormSavedSnackbarTest {
.clickFinalize()
.assertText(org.odk.collect.strings.R.string.form_saved)
.clickOnString(org.odk.collect.strings.R.string.view_form)
.clickOKOnDialog()
.assertText("25")
.assertTextDoesNotExist(org.odk.collect.strings.R.string.jump_to_beginning)
.assertTextDoesNotExist(org.odk.collect.strings.R.string.jump_to_end)
.assertText(org.odk.collect.strings.R.string.exit)
.assertText(org.odk.collect.strings.R.string.jump_to_beginning)
.assertText(org.odk.collect.strings.R.string.jump_to_end)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.odk.collect.android.support.pages.FormEntryPage.QuestionAndAnswer
import org.odk.collect.android.support.pages.MainMenuPage
import org.odk.collect.android.support.pages.OkDialog
import org.odk.collect.android.support.pages.ProjectSettingsPage
import org.odk.collect.android.support.pages.SaveOrDiscardFormDialog
import org.odk.collect.android.support.pages.SendFinalizedFormPage
import org.odk.collect.android.support.rules.CollectTestRule
import org.odk.collect.android.support.rules.TestRuleChain.chain
Expand All @@ -29,13 +30,63 @@ class SendFinalizedFormTest {
.around(rule)

@Test
fun canViewFormsBeforeSending() {
fun canEditAndFinalizeFormsBeforeSending() {
rule.withProject(testDependencies.server.url)
.copyForm("one-question.xml", testDependencies.server.hostName)
.startBlankForm("One Question")
.fillOutAndFinalize(QuestionAndAnswer("what is your age", "52"))
.closeSnackbar() // Make sure we don't get a false positive from this later

.clickSendFinalizedForm(1)
.clickOnFormToEdit("One Question")
.clickGoToStart()
.answerQuestion("what is your age", "53")
.swipeToEndScreen()
.clickFinalize()
.checkIsSnackbarWithMessageDisplayed(org.odk.collect.strings.R.string.form_saved)

.clickSendFinalizedForm(1)
.clickOnFormToEdit("One Question")
.assertText("53")
}

@Test
fun canEditAndConvertToDraftFormsBeforeSending() {
rule.withProject(testDependencies.server.url)
.copyForm("one-question.xml", testDependencies.server.hostName)
.startBlankForm("One Question")
.fillOutAndFinalize(QuestionAndAnswer("what is your age", "52"))
.closeSnackbar() // Make sure we don't get a false positive from this later

.clickSendFinalizedForm(1)
.clickOnFormToEdit("One Question")
.clickGoToStart()
.answerQuestion("what is your age", "53")
.swipeToEndScreen()
.clickSaveAsDraft()
.checkIsSnackbarWithMessageDisplayed(org.odk.collect.strings.R.string.form_saved_as_draft)

.clickEditSavedForm(1)
.clickOnForm("One Question")
.assertText("53")
}

@Test
fun canEditAFormAndLeaveFinalizedBeforeSending() {
rule.withProject(testDependencies.server.url)
.copyForm("one-question.xml", testDependencies.server.hostName)
.startBlankForm("One Question")
.fillOutAndFinalize(QuestionAndAnswer("what is your age", "52"))

.clickSendFinalizedForm(1)
.clickOnFormToEdit("One Question")
.clickGoToStart()
.answerQuestion("what is your age", "53")
.pressBack(SaveOrDiscardFormDialog(MainMenuPage()))
.clickDiscardChanges()

.clickSendFinalizedForm(1)
.clickOnFormToEdit("One Question")
.assertText("52")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ public ViewFormPage clickOnForm(String formLabel) {
return new ViewFormPage(formLabel).assertOnPage();
}

public FormHierarchyPage clickOnFormToEdit(String formLabel) {
clickOnText(formLabel);
clickOKOnDialog();
return new FormHierarchyPage(formLabel).assertOnPage();
}

public OkDialog clickSendSelected() {
clickOnText(getTranslatedString(org.odk.collect.strings.R.string.send_selected_data));
return new OkDialog();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
import org.odk.collect.android.audio.AudioRecordingControllerFragment;
import org.odk.collect.android.audio.M4AAppender;
import org.odk.collect.android.backgroundwork.InstanceSubmitScheduler;
import org.odk.collect.android.dao.helpers.InstancesDaoHelper;
import org.odk.collect.android.entities.EntitiesRepositoryProvider;
import org.odk.collect.android.exception.JavaRosaException;
import org.odk.collect.android.external.FormsContract;
Expand Down Expand Up @@ -1039,7 +1038,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
return true;
} else if (item.getItemId() == R.id.menu_save) {
// don't exit
saveForm(false, InstancesDaoHelper.isInstanceComplete(getFormController()), null, true);
saveForm(false, false, null, true);
return true;
}

Expand Down Expand Up @@ -1966,7 +1965,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
}

QuitFormDialog.show(this, formSaveViewModel, formEntryViewModel, settingsProvider, () -> {
saveForm(true, InstancesDaoHelper.isInstanceComplete(getFormController()), null, true);
saveForm(true, false, null, true);
});
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import android.widget.ListView;
import android.widget.ProgressBar;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
Expand Down Expand Up @@ -134,6 +136,11 @@ public class InstanceUploaderListActivity extends LocalizedActivity implements
private SearchView searchView;
private String savedFilterText;

private final ActivityResultLauncher<Intent> formLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
setResult(RESULT_OK, result.getData());
finish();
});

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down Expand Up @@ -393,7 +400,7 @@ public void onItemClick(AdapterView<?> parent, View view, int position, long row
} else {
long instanceId = c.getLong(c.getColumnIndex(DatabaseInstanceColumns._ID));
Intent intent = FormFillingIntentFactory.editInstanceIntent(this, currentProjectProvider.getCurrentProject().getUuid(), instanceId);
startActivity(intent);
formLauncher.launch(intent);
}
}

Expand All @@ -413,14 +420,14 @@ protected void onSaveInstanceState(Bundle outState) {

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == RESULT_CANCELED) {
multiSelectViewModel.unselectAll();
return;
}

switch (requestCode) {
// returns with a form path, start entry
case INSTANCE_UPLOADER:
if (resultCode == RESULT_CANCELED) {
multiSelectViewModel.unselectAll();
return;
}

if (intent.getBooleanExtra(FormFillingActivity.KEY_SUCCESS, false)) {
listView.clearChoices();
if (listAdapter.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@
package org.odk.collect.android.dao.helpers;

import org.odk.collect.android.application.Collect;
import org.odk.collect.android.javarosawrapper.FormController;
import org.odk.collect.android.utilities.InstancesRepositoryProvider;
import org.odk.collect.forms.instances.Instance;
import org.odk.collect.forms.instances.InstancesRepository;

import timber.log.Timber;

/**
* Provides abstractions over database calls for instances.
*
Expand All @@ -34,34 +31,6 @@ private InstancesDaoHelper() {

}

/**
* Checks the database to determine if the current instance being edited has
* already been 'marked completed'. A form can be 'unmarked' complete and
* then resaved.
*
* @return true if form has been marked completed, false otherwise.
* <p>
* TODO: replace with method in {@link InstancesRepository}
* that returns an {@link Instance} object from a path.
*/
public static boolean isInstanceComplete(FormController formController) {
// default to false if we're mid form
boolean complete = false;

if (formController != null && formController.getInstanceFile() != null) {
// Then see if we've already marked this form as complete before
String path = formController.getInstanceFile().getAbsolutePath();
Instance instance = new InstancesRepositoryProvider(Collect.getInstance()).get().getOneByPath(path);
if (instance != null && instance.getStatus().equals(Instance.STATUS_COMPLETE)) {
complete = true;
}
} else {
Timber.w("FormController or its instanceFile field has a null value");
}

return complete;
}

// TODO: replace with method in {@link org.odk.collect.android.instances.InstancesRepository}
// that returns an {@link Instance} object from a path.
public static boolean isInstanceAvailable(String path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,33 @@ package org.odk.collect.android.external

import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.odk.collect.analytics.Analytics
import org.odk.collect.android.activities.FormFillingActivity
import org.odk.collect.android.analytics.AnalyticsEvents
import org.odk.collect.android.injection.DaggerUtils
import org.odk.collect.android.instancemanagement.InstanceDeleter
import org.odk.collect.android.instancemanagement.canBeEdited
import org.odk.collect.android.projects.CurrentProjectProvider
import org.odk.collect.android.utilities.ApplicationConstants
import org.odk.collect.android.utilities.ContentUriHelper
import org.odk.collect.android.utilities.FormsRepositoryProvider
import org.odk.collect.android.utilities.InstancesRepositoryProvider
import org.odk.collect.forms.Form
import org.odk.collect.forms.instances.Instance
import org.odk.collect.projects.ProjectsRepository
import org.odk.collect.settings.SettingsProvider
import org.odk.collect.settings.keys.ProjectKeys
import org.odk.collect.settings.keys.ProtectedProjectKeys
import org.odk.collect.strings.localization.LocalizedActivity
import java.io.File
import javax.inject.Inject

/**
* This class serves as a firewall for starting form filling. It should be used to do that
* rather than [FormFillingActivity] directly as it ensures that the required data is valid.
*/
class FormUriActivity : ComponentActivity() {
class FormUriActivity : LocalizedActivity() {

@Inject
lateinit var currentProjectProvider: CurrentProjectProvider
Expand Down Expand Up @@ -64,7 +65,16 @@ class FormUriActivity : ComponentActivity() {
!assertNotNewFormInGoogleDriveProject() -> Unit
!assertFormNotEncrypted() -> Unit
!assertFormFillingNotAlreadyStarted(savedInstanceState) -> Unit
else -> startForm()
else -> if (isFormFinalizedButEditable()) {
MaterialAlertDialogBuilder(this)
.setMessage(org.odk.collect.strings.R.string.edit_finalized_form_warning)
.setPositiveButton(org.odk.collect.strings.R.string.ok) { _, _ -> startForm() }
.setCancelable(false)
.create()
.show()
} else {
startForm()
}
}
}

Expand All @@ -78,20 +88,6 @@ class FormUriActivity : ComponentActivity() {
}
}

private fun assertCurrentProjectUsed(): Boolean {
val projects = projectsRepository.getAll()
val firstProject = projects.first()
val uriProjectId = intent.data?.getQueryParameter("projectId")
val projectId = uriProjectId ?: firstProject.uuid

return if (projectId != currentProjectProvider.getCurrentProject().uuid) {
displayErrorDialog(getString(org.odk.collect.strings.R.string.wrong_project_selected_for_form))
false
} else {
true
}
}

private fun assertNotNewFormInGoogleDriveProject(): Boolean {
val uri = intent.data!!
val uriMimeType = contentResolver.getType(uri)
Expand All @@ -109,6 +105,20 @@ class FormUriActivity : ComponentActivity() {
}
}

private fun assertCurrentProjectUsed(): Boolean {
val projects = projectsRepository.getAll()
val firstProject = projects.first()
val uriProjectId = intent.data?.getQueryParameter("projectId")
val projectId = uriProjectId ?: firstProject.uuid

return if (projectId != currentProjectProvider.getCurrentProject().uuid) {
displayErrorDialog(getString(org.odk.collect.strings.R.string.wrong_project_selected_for_form))
false
} else {
true
}
}

private fun assertValidUri(): Boolean {
val isUriValid = intent.data?.let {
val uriMimeType = contentResolver.getType(it)
Expand Down Expand Up @@ -232,6 +242,18 @@ class FormUriActivity : ComponentActivity() {
return formEditingEnabled
}

private fun isFormFinalizedButEditable(): Boolean {
val uri = intent.data!!
val uriMimeType = contentResolver.getType(uri)

return if (uriMimeType == InstancesContract.CONTENT_ITEM_TYPE) {
val instance = instanceRepositoryProvider.get().get(ContentUriHelper.getIdFromUri(uri))
instance!!.status == Instance.STATUS_COMPLETE && instance.canBeEdited(settingsProvider)
} else {
false
}
}

override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(FORM_FILLING_ALREADY_STARTED, formFillingAlreadyStarted)
super.onSaveInstanceState(outState)
Expand All @@ -241,3 +263,8 @@ class FormUriActivity : ComponentActivity() {
private const val FORM_FILLING_ALREADY_STARTED = "FORM_FILLING_ALREADY_STARTED"
}
}

private fun Instance.canBeEdited(settingsProvider: SettingsProvider): Boolean {
return (this.status == Instance.STATUS_INCOMPLETE || this.status == Instance.STATUS_COMPLETE) &&
settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.KEY_EDIT_SAVED)
}
Loading

0 comments on commit ee49671

Please sign in to comment.