Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ProjectManagementPage : Page<ProjectManagementPage>() {

fun deleteProject(): MainMenuPage {
scrollToRecyclerViewItemAndClickText(org.odk.collect.strings.R.string.delete_project)
inputText("delete")
inputText(getTranslatedString(org.odk.collect.strings.R.string.delete_trigger))
clickOnString(org.odk.collect.strings.R.string.delete_project_confirm_button_text)
return MainMenuPage()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class DeleteProjectDialog(
deleteButton.setOnClickListener { viewModel.deleteProject() }

confirmationFieldInput.doAfterTextChanged { text ->
deleteButton.isEnabled = "delete".equals(text.toString().trim(), true)
val deleteTrigger = getString(org.odk.collect.strings.R.string.delete_trigger)
deleteButton.isEnabled = deleteTrigger.equals(text.toString().trim(), true)
}
}

Expand All @@ -71,12 +72,10 @@ class DeleteProjectDialog(
org.odk.collect.strings.R.string.delete_project_dialog_title,
projectData.projectName
)
val message = getString(
org.odk.collect.strings.R.string.delete_project_dialog_message,
val message = createDeleteMessage(
projectData.numberOfForms,
projectData.numberOfSentForms,
projectData.numberOfUnsentForms,
if (projectData.numberOfUnsentForms > 0) "⚠\uFE0F" else "",
projectData.numberOfDraftForms
)
binding.message.text = HtmlCompat.fromHtml(message, HtmlCompat.FROM_HTML_MODE_LEGACY)
Expand All @@ -98,12 +97,14 @@ class DeleteProjectDialog(
)
)
}

is DeleteProjectResult.DeletedSuccessfullyLastProject -> {
ActivityUtils.startActivityAndCloseAllOthers(
requireActivity(),
FirstLaunchActivity::class.java
)
}

is DeleteProjectResult.DeletedSuccessfullyInactiveProject -> {
// not possible here
}
Expand All @@ -115,6 +116,40 @@ class DeleteProjectDialog(
.create()
}

private fun createDeleteMessage(
formDefinitionsCount: Int,
sentCount: Int,
unsentCount: Int,
draftsCount: Int
): String {
val message = getString(org.odk.collect.strings.R.string.delete_project_message)
val formDefinitions =
getString(org.odk.collect.strings.R.string.form_definitions_count, formDefinitionsCount)
val sent = getString(org.odk.collect.strings.R.string.sent_count, sentCount)
val drafts = getString(org.odk.collect.strings.R.string.drafts_count, draftsCount)
val unsent = if (unsentCount > 0) {
"${getString(org.odk.collect.strings.R.string.unsent_count, unsentCount)} ⚠\uFE0F"
} else {
getString(org.odk.collect.strings.R.string.unsent_count, unsentCount)
}

val instructions = getString(
org.odk.collect.strings.R.string.delete_project_instructions,
"<b>${getString(org.odk.collect.strings.R.string.delete_trigger)}</b>"
)

return """
$message:<br/>
<br/>
• $formDefinitions<br/>
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious to see how this will look with a RTL language! I think if it's not great we can file it as a low-priority issue.

• $sent<br/>
• $unsent<br/>
• $drafts<br/>
<br/>
$instructions
"""
}

class DeleteProjectViewModel(
projectsDataService: ProjectsDataService,
private val projectDeleter: ProjectDeleter,
Expand All @@ -140,7 +175,8 @@ class DeleteProjectDialog(
instancesDataService.update(project.uuid)

val numberOfForms = formsDataService.getFormsCount(project.uuid).value
val numberOfSentForms = instancesDataService.getSuccessfullySentCount(project.uuid).value
val numberOfSentForms =
instancesDataService.getSuccessfullySentCount(project.uuid).value
val numberOfUnsentForms = instancesDataService.getSendableCount(project.uuid).value
val numberOfDraftForms = instancesDataService.getEditableCount(project.uuid).value
_projectData.postValue(
Expand Down
39 changes: 19 additions & 20 deletions collect_app/src/main/res/layout/delete_project_dialog_layout.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
Expand All @@ -16,22 +15,22 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_standard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/delete_project_dialog_title"
android:textAppearance="?textAppearanceHeadlineSmall"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/delete_project_dialog_title"
android:textAppearance="?textAppearanceHeadlineSmall"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progress_bar"
app:layout_goneMarginTop="@dimen/margin_standard"
tools:text="Delete X project"/>
tools:text="Delete X project" />

<com.google.android.material.textview.MaterialTextView
android:id="@+id/message"
Expand All @@ -41,33 +40,33 @@
android:textAppearance="?textAppearanceBodyMedium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="@string/delete_project_dialog_message"/>
tools:text="Delete project message" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/confirmation_field"
style="?textInputFilledStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_standard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/message">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/confirmation_field_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="@dimen/margin_standard"
android:inputType="text"
android:lines="1" />
android:lines="1"
android:paddingVertical="@dimen/margin_standard" />
</com.google.android.material.textfield.TextInputLayout>

<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrierTopViews"
app:barrierDirection="bottom"
app:constraint_referenced_ids="progress_bar, confirmation_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="progress_bar, confirmation_field" />

<org.odk.collect.androidshared.ui.multiclicksafe.MultiClickSafeMaterialButton
android:id="@+id/cancel_button"
Expand All @@ -76,25 +75,25 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_extra_large"
android:text="@string/cancel"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrierTopViews" />

<org.odk.collect.androidshared.ui.multiclicksafe.MultiClickSafeMaterialButton
android:id="@+id/delete_button"
style="?materialButtonIconStyle"
android:textColor="@android:color/white"
android:backgroundTint="@color/color_error_button_icon"
android:enabled="false"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_extra_small"
android:backgroundTint="@color/color_error_button_icon"
android:enabled="false"
android:text="@string/delete_project_confirm_button_text"
android:textColor="@android:color/white"
app:icon="@drawable/ic_delete"
app:iconGravity="textStart"
app:iconTint="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cancel_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</ScrollView>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.odk.collect.android.preferences.dialogs

import android.app.Application
import android.text.TextUtils
import androidx.core.text.HtmlCompat
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
Expand All @@ -23,6 +22,7 @@ import com.google.android.material.textview.MaterialTextView
import kotlinx.coroutines.flow.MutableStateFlow
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.CoreMatchers.not
import org.hamcrest.Matchers.containsString
import org.junit.Before
import org.junit.Rule
import org.junit.Test
Expand All @@ -49,7 +49,7 @@ import org.odk.collect.projects.Project
import org.odk.collect.projects.ProjectsRepository
import org.odk.collect.settings.SettingsProvider
import org.odk.collect.strings.R.string
import org.odk.collect.strings.localization.getLocalizedString
import org.odk.collect.testshared.Assertions
import org.odk.collect.testshared.FakeScheduler

@RunWith(AndroidJUnit4::class)
Expand Down Expand Up @@ -186,40 +186,47 @@ class DeleteProjectDialogTest {
@Test
fun `The message shows the correct number of blank forms`() {
whenever(formsDataService.getFormsCount(projectId)).thenReturn(MutableStateFlow(1))
val message = HtmlCompat.fromHtml(
context.getLocalizedString(string.delete_project_dialog_message, 1, 0, 0, "", 0),
HtmlCompat.FROM_HTML_MODE_LEGACY
).toString()

launcherRule.launch(DeleteProjectDialog::class.java)
scheduler.flush()
onView(withText(message)).inRoot(isDialog()).check(matches(isDisplayed()))
assertCounts(forms = 1, sent = 0, unsent = 0, drafts = 0)
}

@Test
fun `The message shows the correct number of sent forms`() {
whenever(instancesDataService.getSuccessfullySentCount(projectId)).thenReturn(MutableStateFlow(1))
val message = HtmlCompat.fromHtml(
context.getLocalizedString(string.delete_project_dialog_message, 0, 1, 0, "", 0),
HtmlCompat.FROM_HTML_MODE_LEGACY
).toString()

launcherRule.launch(DeleteProjectDialog::class.java)
scheduler.flush()
onView(withText(message)).inRoot(isDialog()).check(matches(isDisplayed()))
assertCounts(forms = 0, sent = 1, unsent = 0, drafts = 0)
}

@Test
fun `The message shows the correct number of unsent forms and drafts`() {
whenever(instancesDataService.getSendableCount(projectId)).thenReturn(MutableStateFlow(5))
whenever(instancesDataService.getEditableCount(projectId)).thenReturn(MutableStateFlow(3))
val message = HtmlCompat.fromHtml(
context.getLocalizedString(string.delete_project_dialog_message, 0, 0, 5, "⚠\uFE0F", 3),
HtmlCompat.FROM_HTML_MODE_LEGACY
).toString()

launcherRule.launch(DeleteProjectDialog::class.java)
scheduler.flush()
onView(withText(message)).inRoot(isDialog()).check(matches(isDisplayed()))
assertCounts(forms = 0, sent = 0, unsent = 5, drafts = 3)
}

private fun assertCounts(forms: Int, sent: Int, unsent: Int, drafts: Int) {
Assertions.assertVisible(
view = withText(containsString(context.getString(string.form_definitions_count, forms))),
root = isDialog()
)
Assertions.assertVisible(
view = withText(containsString(context.getString(string.sent_count, sent))),
root = isDialog()
)
Assertions.assertVisible(
view = withText(containsString(context.getString(string.unsent_count, unsent))),
root = isDialog()
)
Assertions.assertVisible(
view = withText(containsString(context.getString(string.drafts_count, drafts))),
root = isDialog()
)
}
}
24 changes: 16 additions & 8 deletions strings/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1142,14 +1142,22 @@
<string name="switch_to_project">Switch to %s</string>
<!-- Text for the dialog title displayed when a user attempts to delete the current project -->
<string name="delete_project_dialog_title">Delete %s</string>
<!-- Text for the dialog message displayed when a user attempts to delete the current project -->
<string name="delete_project_dialog_message">By deleting this project, you will permanently delete the following:&lt;br/&gt;&lt;br/&gt;
• Form Definitions: %1$d&lt;br/&gt;
• Sent: %2$d&lt;br/&gt;
• Unsent: %3$d %4$s&lt;br/&gt;
• Drafts: %5$d&lt;br/&gt;&lt;br/&gt;
Type &lt;b&gt;Delete&lt;/b&gt; to confirm this action.
</string>

<!-- Text that appears above the list of counts of different kinds of forms shown before deleting a project -->
<string name="delete_project_message">By deleting this project, you will permanently delete the following</string>
<!-- Instructions telling the user they need to type a specific word to confirm deletion of the project -->
<string name="delete_project_instructions">Type %1$s to confirm this action.</string>
<!-- The word that needs to be typed to confirm deletion of the form. Should be all lowercase to allow for case insensitive matching -->
<string name="delete_trigger">delete</string>
<!-- The list item for form definition count in the project delete confirmation dialog -->
<string name="form_definitions_count">Form definitions: %1$d</string>
<!-- The list item for sent count in the project delete confirmation dialog -->
<string name="sent_count">Sent: %1$d</string>
<!-- The list item for unsent count in the project delete confirmation dialog -->
<string name="unsent_count">Unsent: %1$d</string>
<!-- The list item for draft count in the project delete confirmation dialog -->
<string name="drafts_count">Drafts: %1$d</string>

<!-- Text for the button that confirms deleting the project -->
<string name="delete_project_confirm_button_text">Delete project</string>
<string name="or">OR</string>
Expand Down