Skip to content

Commit 467c317

Browse files
authored
Merge pull request #6516 from seadowg/view-only
Convert hierarchy to Fragment
2 parents 184e878 + 9aec982 commit 467c317

24 files changed

+1216
-1188
lines changed

collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/AddRepeatTest.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.junit.runner.RunWith;
1313
import org.odk.collect.android.R;
1414
import org.odk.collect.android.support.pages.EndOfFormPage;
15+
import org.odk.collect.android.support.pages.FormEndPage;
1516
import org.odk.collect.android.support.pages.FormEntryPage;
1617
import org.odk.collect.android.support.rules.CollectTestRule;
1718
import org.odk.collect.android.support.rules.TestRuleChain;
@@ -106,7 +107,7 @@ public void whenInRepeatWithFixedCount_noPlusButtonAppears() {
106107
}
107108

108109
@Test
109-
public void whenInHierarchyForRepeat_clickingPlus_addsRepeatAtEndOfSeries() {
110+
public void whenInHierarchyForRepeatGroup_clickingPlus_addsRepeatAtEndOfSeries() {
110111
rule.startAtMainMenu()
111112
.copyForm(ONE_QUESTION_REPEAT)
112113
.startBlankForm("One Question Repeat")
@@ -130,4 +131,19 @@ public void whenInRepeatWithoutLabel_swipingNext_andClickingAdd_addsAnotherRepea
130131
.clickOnAdd(new FormEntryPage("Repeat without label"))
131132
.assertText("> 2");
132133
}
134+
135+
@Test
136+
public void whenViewFormInHierarchyForRepeatGroup_noAddButtonAppears() {
137+
rule.startAtMainMenu()
138+
.copyForm(ONE_QUESTION_REPEAT)
139+
.startBlankForm("One Question Repeat")
140+
.swipeToNextQuestionWithRepeatGroup("Person")
141+
.clickOnDoNotAdd(new FormEndPage("One Question Repeat"))
142+
.clickFinalize()
143+
144+
.clickSendFinalizedForm(1)
145+
.clickOnForm("One Question Repeat")
146+
.clickOnGroup("Person")
147+
.assertNoId(R.id.menu_add_repeat);
148+
}
133149
}

collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/FormHierarchyTest.java

+34-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
import org.junit.Test;
1111
import org.junit.rules.RuleChain;
1212
import org.odk.collect.android.R;
13-
import org.odk.collect.android.support.rules.CollectTestRule;
14-
import org.odk.collect.android.support.rules.TestRuleChain;
15-
import org.odk.collect.testshared.RecyclerViewMatcher;
1613
import org.odk.collect.android.support.pages.AddNewRepeatDialog;
14+
import org.odk.collect.android.support.pages.FormEndPage;
1715
import org.odk.collect.android.support.pages.FormEntryPage;
1816
import org.odk.collect.android.support.pages.FormHierarchyPage;
17+
import org.odk.collect.android.support.pages.ViewFormPage;
18+
import org.odk.collect.android.support.rules.CollectTestRule;
19+
import org.odk.collect.android.support.rules.TestRuleChain;
20+
import org.odk.collect.testshared.RecyclerViewMatcher;
1921

2022
public class FormHierarchyTest {
2123

@@ -238,4 +240,33 @@ public void theListOfQuestionsShouldBeScrolledToTheLastDisplayedQuestionAfterOpe
238240
.assertTextDoesNotExist("t1")
239241
.assertTextDoesNotExist("t2");
240242
}
243+
244+
@Test
245+
public void whenViewFormInHierarchyForRepeatGroup_noDeleteButtonAppears() {
246+
rule.startAtMainMenu()
247+
.copyForm("one-question-repeat.xml")
248+
.startBlankForm("One Question Repeat")
249+
.swipeToNextQuestionWithRepeatGroup("Person")
250+
.clickOnDoNotAdd(new FormEndPage("One Question Repeat"))
251+
.clickFinalize()
252+
253+
.clickSendFinalizedForm(1)
254+
.clickOnForm("One Question Repeat")
255+
.clickOnGroup("Person")
256+
.clickOnGroup("Person > 1")
257+
.assertNoId(R.id.menu_delete_child);
258+
}
259+
260+
@Test
261+
public void whenViewFormInHierarchy_clickingOnQuestion_doesNothing() {
262+
rule.startAtMainMenu()
263+
.copyForm("one-question.xml")
264+
.startBlankForm("One Question")
265+
.fillOutAndFinalize()
266+
267+
.clickSendFinalizedForm(1)
268+
.clickOnForm("One Question")
269+
.clickOnText("what is your age")
270+
.assertOnPage(new ViewFormPage("One Question"));
271+
}
241272
}

collect_app/src/androidTest/java/org/odk/collect/android/support/pages/Page.kt

+5
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,11 @@ abstract class Page<T : Page<T>> {
574574
return destination
575575
}
576576

577+
fun assertNoId(id: Int): T {
578+
onView(withId(id)).check(doesNotExist())
579+
return this as T
580+
}
581+
577582
companion object {
578583
private fun rotateToLandscape(): ViewAction {
579584
return RotateAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
package org.odk.collect.android.support.pages
22

3+
import androidx.recyclerview.widget.RecyclerView
4+
import androidx.test.espresso.Espresso.onView
5+
import androidx.test.espresso.contrib.RecyclerViewActions.scrollTo
6+
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
7+
import androidx.test.espresso.matcher.ViewMatchers.withId
8+
import androidx.test.espresso.matcher.ViewMatchers.withText
9+
import org.odk.collect.android.R
10+
311
class ViewFormPage(private val formName: String) : Page<ViewFormPage>() {
412

513
override fun assertOnPage(): ViewFormPage {
614
assertToolbarTitle(formName)
715
assertText(org.odk.collect.strings.R.string.exit)
816
return this
917
}
18+
19+
fun clickOnGroup(groupLabel: String): ViewFormPage {
20+
onView(withId(R.id.list)).perform(scrollTo<RecyclerView.ViewHolder>(
21+
hasDescendant(withText(groupLabel)))
22+
)
23+
24+
clickOnText(groupLabel)
25+
return this
26+
}
1027
}

collect_app/src/main/AndroidManifest.xml

+1-2
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,6 @@ the specific language governing permissions and limitations under the License.
143143
<activity
144144
android:name=".preferences.screens.ProjectPreferencesActivity"
145145
android:theme="@style/Theme.Collect.Settings" />
146-
<activity android:name=".formhierarchy.FormHierarchyActivity" />
147-
<activity android:name=".formhierarchy.ViewOnlyFormHierarchyActivity" />
148146
<activity
149147
android:name="org.odk.collect.geo.geopoint.GeoPointActivity"
150148
android:theme="@style/Theme.Collect"
@@ -328,6 +326,7 @@ the specific language governing permissions and limitations under the License.
328326
<data android:mimeType="vnd.android.cursor.item/vnd.odk.instance" />
329327
</intent-filter>
330328
</activity>
329+
<activity android:name="org.odk.collect.android.formhierarchy.FormHierarchyFragmentHostActivity" />
331330

332331
</application>
333332

collect_app/src/main/java/org/odk/collect/android/activities/FormFillingActivity.java

+10-9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.javarosa.form.api.FormEntryController.EVENT_PROMPT_NEW_REPEAT;
2121
import static org.odk.collect.android.formentry.FormIndexAnimationHandler.Direction.BACKWARDS;
2222
import static org.odk.collect.android.formentry.FormIndexAnimationHandler.Direction.FORWARDS;
23+
import static org.odk.collect.android.formentry.repeats.DeleteRepeatDialogFragment.REQUEST_DELETE_REPEAT;
2324
import static org.odk.collect.android.utilities.AnimationUtils.areAnimationsEnabled;
2425
import static org.odk.collect.android.utilities.ApplicationConstants.RequestCodes;
2526
import static org.odk.collect.android.utilities.DialogUtils.getDialog;
@@ -124,8 +125,7 @@
124125
import org.odk.collect.android.formentry.saving.SaveAnswerFileErrorDialogFragment;
125126
import org.odk.collect.android.formentry.saving.SaveAnswerFileProgressDialogFragment;
126127
import org.odk.collect.android.formentry.saving.SaveFormProgressDialogFragment;
127-
import org.odk.collect.android.formhierarchy.FormHierarchyActivity;
128-
import org.odk.collect.android.formhierarchy.ViewOnlyFormHierarchyActivity;
128+
import org.odk.collect.android.formhierarchy.FormHierarchyFragmentHostActivity;
129129
import org.odk.collect.android.fragments.MediaLoadingFragment;
130130
import org.odk.collect.android.fragments.dialogs.LocationProvidersDisabledDialog;
131131
import org.odk.collect.android.fragments.dialogs.NumberPickerDialog;
@@ -229,7 +229,6 @@ public class FormFillingActivity extends LocalizedActivity implements AnimationL
229229
RankingWidgetDialog.RankingListener, SaveFormIndexTask.SaveFormIndexListener,
230230
WidgetValueChangedListener, ScreenContext, FormLoadingDialogFragment.FormLoadingDialogFragmentListener,
231231
AudioControllerView.SwipableParent, FormIndexAnimationHandler.Listener,
232-
DeleteRepeatDialogFragment.DeleteRepeatDialogCallback,
233232
SelectMinimalDialog.SelectMinimalDialogListener, CustomDatePickerDialog.DateChangeListener,
234233
CustomTimePickerDialog.TimeChangeListener {
235234

@@ -449,6 +448,8 @@ public void onCreate(Bundle savedInstanceState) {
449448
.forClass(SelectOneFromMapDialogFragment.class, () -> new SelectOneFromMapDialogFragment(viewModelFactory))
450449
.build());
451450

451+
getSupportFragmentManager().setFragmentResultListener(REQUEST_DELETE_REPEAT, this, (requestKey, result) -> deleteGroup());
452+
452453
if (ProcessRestoreDetector.isProcessRestoring(this, savedInstanceState)) {
453454
if (savedInstanceState.containsKey(KEY_XPATH)) {
454455
startingXPath = savedInstanceState.getString(KEY_XPATH);
@@ -1057,7 +1058,6 @@ public boolean onContextItemSelected(MenuItem item) {
10571058
return super.onContextItemSelected(item);
10581059
}
10591060

1060-
@Override
10611061
public void deleteGroup() {
10621062
FormController formController = getFormController();
10631063
if (formController != null && !formController.indexIsInFieldList()) {
@@ -1899,7 +1899,7 @@ public void onAnimationStart(Animation animation) {
18991899

19001900
/**
19011901
* Given a {@link FormLoaderTask} which has created a {@link FormController} for either a new or
1902-
* existing instance, shows that instance to the user. Either launches {@link FormHierarchyActivity}
1902+
* existing instance, shows that instance to the user. Either launches {@link FormHierarchyFragmentHostActivity}
19031903
* if an existing instance is being edited or builds the view for the current question(s) if a
19041904
* new instance is being created.
19051905
* <p>
@@ -2030,17 +2030,18 @@ && new PlayServicesChecker().isGooglePlayServicesAvailable(this)) {
20302030
} else {
20312031
formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.HIERARCHY, true, System.currentTimeMillis());
20322032
formControllerAvailable(formController, form, instance);
2033-
Intent intent = new Intent(this, FormHierarchyActivity.class);
2034-
intent.putExtra(FormHierarchyActivity.EXTRA_SESSION_ID, sessionId);
2033+
Intent intent = new Intent(this, FormHierarchyFragmentHostActivity.class);
2034+
intent.putExtra(FormHierarchyFragmentHostActivity.EXTRA_SESSION_ID, sessionId);
20352035
startActivityForResult(intent, RequestCodes.HIERARCHY_ACTIVITY);
20362036
}
20372037
}
20382038
});
20392039
} else {
20402040
formControllerAvailable(formController, form, instance);
20412041
if (ApplicationConstants.FormModes.VIEW_SENT.equalsIgnoreCase(formMode)) {
2042-
Intent intent = new Intent(this, ViewOnlyFormHierarchyActivity.class);
2043-
intent.putExtra(FormHierarchyActivity.EXTRA_SESSION_ID, sessionId);
2042+
Intent intent = new Intent(this, FormHierarchyFragmentHostActivity.class);
2043+
intent.putExtra(FormHierarchyFragmentHostActivity.EXTRA_SESSION_ID, sessionId);
2044+
intent.putExtra(FormHierarchyFragmentHostActivity.EXTRA_VIEW_ONLY, true);
20442045
startActivity(intent);
20452046
}
20462047

collect_app/src/main/java/org/odk/collect/android/formentry/FormEntryMenuProvider.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
1212
import org.odk.collect.android.R
1313
import org.odk.collect.android.formentry.backgroundlocation.BackgroundLocationViewModel
1414
import org.odk.collect.android.formentry.questions.AnswersProvider
15-
import org.odk.collect.android.formhierarchy.FormHierarchyActivity
15+
import org.odk.collect.android.formhierarchy.FormHierarchyFragmentHostActivity
1616
import org.odk.collect.android.preferences.screens.ProjectPreferencesActivity
1717
import org.odk.collect.android.utilities.ApplicationConstants
1818
import org.odk.collect.androidshared.system.PlayServicesChecker
@@ -126,8 +126,8 @@ class FormEntryMenuProvider(
126126
} else {
127127
formEntryViewModel.updateAnswersForScreen(answersProvider.answers, false)
128128
formEntryViewModel.openHierarchy()
129-
val i = Intent(activity, FormHierarchyActivity::class.java)
130-
i.putExtra(FormHierarchyActivity.EXTRA_SESSION_ID, formEntryViewModel.sessionId)
129+
val i = Intent(activity, FormHierarchyFragmentHostActivity::class.java)
130+
i.putExtra(FormHierarchyFragmentHostActivity.EXTRA_SESSION_ID, formEntryViewModel.sessionId)
131131
activity.startActivityForResult(i, ApplicationConstants.RequestCodes.HIERARCHY_ACTIVITY)
132132
}
133133
true

collect_app/src/main/java/org/odk/collect/android/formentry/repeats/DeleteRepeatDialogFragment.java

+3-11
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323

2424
public class DeleteRepeatDialogFragment extends DialogFragment {
2525

26+
public static final String REQUEST_DELETE_REPEAT = "DELETE_REPEAT";
27+
2628
private final ViewModelProvider.Factory viewModelFactory;
2729
private FormEntryViewModel formEntryViewModel;
2830

29-
private DeleteRepeatDialogCallback callback;
30-
3131
public DeleteRepeatDialogFragment(ViewModelProvider.Factory viewModelFactory) {
3232
this.viewModelFactory = viewModelFactory;
3333
}
@@ -38,10 +38,6 @@ public void onAttach(@NonNull Context context) {
3838
DaggerUtils.getComponent(context).inject(this);
3939

4040
formEntryViewModel = new ViewModelProvider(requireActivity(), viewModelFactory).get(FormEntryViewModel.class);
41-
42-
if (context instanceof DeleteRepeatDialogCallback) {
43-
callback = (DeleteRepeatDialogCallback) context;
44-
}
4541
}
4642

4743
@NonNull
@@ -64,7 +60,7 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
6460
if (i == BUTTON_POSITIVE) { // yes
6561
formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.DELETE_REPEAT, true, System.currentTimeMillis());
6662
formController.deleteRepeat();
67-
callback.deleteGroup();
63+
getParentFragmentManager().setFragmentResult(REQUEST_DELETE_REPEAT, new Bundle());
6864
}
6965
alertDialog.cancel();
7066
dismiss();
@@ -76,8 +72,4 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
7672

7773
return alertDialog;
7874
}
79-
80-
public interface DeleteRepeatDialogCallback {
81-
void deleteGroup();
82-
}
8375
}

0 commit comments

Comments
 (0)