Skip to content
Open
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 @@ -63,9 +63,11 @@ import org.groundplatform.domain.repository.SurveyRepositoryInterface
import org.groundplatform.domain.repository.UserRepositoryInterface
import org.groundplatform.domain.usecases.GetLoiReportUseCase
import org.groundplatform.domain.usecases.survey.GetDataSharingTermsUseCase
import org.groundplatform.domain.usecases.user.GetUserSettingsUseCase
import org.groundplatform.domain.util.Constants.CLUSTERING_ZOOM_THRESHOLD
import org.groundplatform.feature.pdf.LoiReportExporter
import org.groundplatform.ui.components.loireport.LoiReportAction
import org.groundplatform.ui.util.getFormattedArea
import timber.log.Timber

@OptIn(ExperimentalCoroutinesApi::class)
Expand All @@ -85,6 +87,7 @@ internal constructor(
private val userRepository: UserRepositoryInterface,
private val locationOfInterestHelper: LocationOfInterestHelper,
private val getLoiReportUseCase: GetLoiReportUseCase,
private val getUserSettingsUseCase: GetUserSettingsUseCase,
private val loiReportExporter: LoiReportExporter,
) :
BaseMapViewModel(
Expand Down Expand Up @@ -233,6 +236,11 @@ internal constructor(
submissionCount = submissionRepository.getTotalSubmissionCount(loi),
showDeleteLoiButton = canDelete,
loiReport = loiReport,
formattedArea =
loi.geometry
.area()
.takeIf { it > 0.0 }
?.let { getFormattedArea(it, getUserSettingsUseCase().measurementUnits) },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ data class SelectedLoiSheetData(
val submissionCount: Int,
val showDeleteLoiButton: Boolean,
val loiReport: LoiReport?,
val formattedArea: String? = null,
) : DataCollectionEntryPointData

data class AdHocDataCollectionButtonData(override val canCollectData: Boolean, val job: Job) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonObject
import org.groundplatform.android.R
import org.groundplatform.android.ui.common.ExcludeFromJacocoGeneratedReport
import org.groundplatform.android.ui.common.LocationOfInterestHelper
Expand All @@ -58,6 +59,7 @@ import org.groundplatform.domain.model.job.Job
import org.groundplatform.domain.model.job.Style
import org.groundplatform.domain.model.locationofinterest.AuditInfo
import org.groundplatform.domain.model.locationofinterest.LocationOfInterest
import org.groundplatform.domain.model.locationofinterest.LoiReport
import org.groundplatform.domain.model.task.Task
import org.groundplatform.ui.components.ShareButton
import org.groundplatform.ui.theme.AppTheme
Expand All @@ -81,11 +83,7 @@ fun LoiJobSheet(
dragHandle = { BottomSheetDefaults.DragHandle(width = 32.dp) },
) {
ModalContents(
loi = state.loi,
canUserSubmitData = state.canCollectData,
submissionCount = state.submissionCount,
showDeleteLoiButton = state.showDeleteLoiButton,
showShareButton = state.loiReport != null,
state = state,
onDeleteClicked = onDeleteClicked,
onCollectClicked = {
scope.launch { sheetState.hide() }.invokeOnCompletion { onCollectClicked() }
Expand All @@ -97,11 +95,7 @@ fun LoiJobSheet(

@Composable
private fun ModalContents(
loi: LocationOfInterest,
canUserSubmitData: Boolean,
submissionCount: Int,
showDeleteLoiButton: Boolean,
showShareButton: Boolean,
state: SelectedLoiSheetData,
onDeleteClicked: (() -> Unit)?,
onCollectClicked: () -> Unit,
onShareClicked: () -> Unit,
Expand All @@ -111,19 +105,20 @@ private fun ModalContents(
val showDeleteDialog = remember { mutableStateOf(false) }

Column(modifier = Modifier.fillMaxWidth().padding(start = 24.dp, end = 24.dp, bottom = 50.dp)) {
JobName(loiHelper = loiHelper, loi = loi)
LoiHeader(loiHelper = loiHelper, loi = loi)
JobName(loiHelper = loiHelper, loi = state.loi)
LoiHeader(loiHelper = loiHelper, loi = state.loi)
SubmissionRow(
loi = loi,
submissionCount = submissionCount,
canUserSubmitData = canUserSubmitData,
showShareButton = showShareButton,
loi = state.loi,
formattedArea = state.formattedArea,
submissionCount = state.submissionCount,
canUserSubmitData = state.canCollectData,
showShareButton = state.loiReport != null,
onCollectClicked = onCollectClicked,
onShareClicked = onShareClicked,
)
DeleteSiteSection(
showDeleteLoiButton = showDeleteLoiButton,
isPredefined = loi.isPredefined == true,
showDeleteLoiButton = state.showDeleteLoiButton,
isPredefined = state.loi.isPredefined == true,
onClick = { showDeleteDialog.value = true },
)
}
Expand Down Expand Up @@ -173,13 +168,21 @@ private fun LoiHeader(loiHelper: LocationOfInterestHelper, loi: LocationOfIntere
@Composable
private fun SubmissionRow(
loi: LocationOfInterest,
formattedArea: String?,
submissionCount: Int,
canUserSubmitData: Boolean,
showShareButton: Boolean,
onCollectClicked: () -> Unit,
onShareClicked: () -> Unit,
) {
Column(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.Top) {
if (formattedArea != null) {
Text(
stringResource(R.string.area_message, formattedArea),
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodyLarge,
)
}
Text(
if (submissionCount <= 0) stringResource(R.string.no_submissions)
else pluralStringResource(R.plurals.submission_count, submissionCount, submissionCount),
Expand Down Expand Up @@ -241,6 +244,21 @@ private val user = User(id = "user", email = "user@email.com", displayName = "Us
private val auditInfo = AuditInfo(user)
private const val SURVEY_ID = "survey"
private const val TASK_ID = "task 1"
private const val AREA = "1.20 ha"
private val loiReport =
LoiReport(
loiName = "Point A",
geoJson = JsonObject(mapOf()),
submissionDetails =
LoiReport.SubmissionDetails(
surveyName = "Test Survey",
userName = "John Doe",
userEmail = "john.doe@example.com",
submissions = emptyList(),
geometry = Point(Coordinates(0.0, 0.0)),
style = null,
),
)

@SuppressLint("UnrememberedMutableState")
@Composable
Expand All @@ -258,11 +276,15 @@ private fun PreviewModalContentsWhenJobHasNoTasks() {
)
AppTheme {
ModalContents(
loi = loi,
canUserSubmitData = true,
submissionCount = 0,
showDeleteLoiButton = false,
showShareButton = true,
state =
SelectedLoiSheetData(
loi = loi,
canCollectData = true,
submissionCount = 0,
showDeleteLoiButton = false,
loiReport = loiReport,
formattedArea = AREA,
),
onDeleteClicked = null,
onShareClicked = {},
onCollectClicked = {},
Expand Down Expand Up @@ -303,11 +325,15 @@ private fun PreviewModalContentsWhenUserCannotSubmitData() {
)
AppTheme {
ModalContents(
loi = loi,
canUserSubmitData = false,
submissionCount = 1,
showDeleteLoiButton = false,
showShareButton = true,
state =
SelectedLoiSheetData(
loi = loi,
canCollectData = false,
submissionCount = 1,
showDeleteLoiButton = false,
loiReport = loiReport,
formattedArea = AREA,
),
onDeleteClicked = null,
onShareClicked = {},
onCollectClicked = {},
Expand Down Expand Up @@ -350,11 +376,15 @@ private fun PreviewModalContentsWhenJobHasTasks() {
)
AppTheme {
ModalContents(
loi = loi,
canUserSubmitData = true,
submissionCount = 20,
showDeleteLoiButton = false,
showShareButton = true,
state =
SelectedLoiSheetData(
loi = loi,
canCollectData = true,
submissionCount = 20,
showDeleteLoiButton = false,
loiReport = loiReport,
formattedArea = AREA,
),
onDeleteClicked = null,
onShareClicked = {},
onCollectClicked = {},
Expand Down Expand Up @@ -397,11 +427,15 @@ private fun PreviewModalContentsWhenJobHasTasksAndIsPredefined() {
)
AppTheme {
ModalContents(
loi = loi,
canUserSubmitData = true,
submissionCount = 20,
showDeleteLoiButton = true,
showShareButton = true,
state =
SelectedLoiSheetData(
loi = loi,
canCollectData = true,
submissionCount = 20,
showDeleteLoiButton = true,
loiReport = loiReport,
formattedArea = AREA,
),
onDeleteClicked = null,
onShareClicked = {},
onCollectClicked = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import org.groundplatform.android.ui.home.mapcontainer.jobs.JobMapComponentState
import org.groundplatform.android.ui.home.mapcontainer.jobs.SelectedLoiSheetData
import org.groundplatform.domain.model.Survey
import org.groundplatform.domain.model.geometry.Coordinates
import org.groundplatform.domain.model.geometry.LinearRing
import org.groundplatform.domain.model.geometry.Polygon
import org.groundplatform.domain.model.map.Bounds
import org.groundplatform.domain.model.map.CameraPosition
import org.groundplatform.domain.repository.LocationOfInterestRepositoryInterface
Expand Down Expand Up @@ -117,6 +119,22 @@ class HomeScreenMapContainerViewModelTest : BaseHiltTest() {
)
}

@Test
fun `job card shows the LOI area in the user's measurement units`() = runWithTestDispatcher {
val areaLoi = LOCATION_OF_INTEREST.copy(geometry = ONE_HECTARE_POLYGON)
whenever(loiRepository.getWithinBounds(SURVEY, BOUNDS)).thenReturn(flowOf(listOf(areaLoi)))
viewModel.onMapCameraMoved(CAMERA_POSITION)
advanceUntilIdle()

viewModel.onFeatureClicked(
features = setOf(LOCATION_OF_INTEREST_FEATURE.copy(geometry = ONE_HECTARE_POLYGON))
)
val state = viewModel.processJobMapComponentState().first()
advanceUntilIdle()

assertThat((state as JobMapComponentState.LoiSelected).loi.formattedArea).isEqualTo("1.00 ha")
}

@Test
fun `deleteLoi deletes the loi and deselects it`() = runWithTestDispatcher {
viewModel.onFeatureClicked(setOf(LOCATION_OF_INTEREST_FEATURE))
Expand Down Expand Up @@ -326,6 +344,18 @@ class HomeScreenMapContainerViewModelTest : BaseHiltTest() {

companion object {
private val BOUNDS = Bounds(Coordinates(-20.0, -20.0), Coordinates(-10.0, -10.0))
private val ONE_HECTARE_POLYGON =
Polygon(
LinearRing(
listOf(
Coordinates(0.0, 0.0),
Coordinates(0.0, 0.0009),
Coordinates(0.0009, 0.0009),
Coordinates(0.0009, 0.0),
Coordinates(0.0, 0.0),
)
)
)
val CAMERA_POSITION =
CameraPosition(
coordinates = LOCATION_OF_INTEREST.geometry.center(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,27 @@ class LoiJobSheetTest {
composeTestRule.onNodeWithText(getString(Res.string.share)).assertIsNotDisplayed()
}

@Test
fun `area is shown when not null`() {
setContent(FREE_FORM_LOI, formattedArea = "1.20 ha")

composeTestRule.onNodeWithText(getString(R.string.area_message, "1.20 ha")).assertIsDisplayed()
}

@Test
fun `area is not shown when null`() {
setContent(FREE_FORM_LOI, formattedArea = null)

composeTestRule
.onNodeWithText(getString(R.string.area_message, "1.20 ha"))
.assertIsNotDisplayed()
}

private fun setContent(
loi: LocationOfInterest,
showDeleteLoiButton: Boolean = false,
loiReport: LoiReport? = getLoiReport(loi.id),
formattedArea: String? = null,
) {
composeTestRule.setContent {
LoiJobSheet(
Expand All @@ -115,6 +132,7 @@ class LoiJobSheetTest {
loi = loi,
showDeleteLoiButton = showDeleteLoiButton,
loiReport = loiReport,
formattedArea = formattedArea,
),
onCollectClicked = {},
onDismiss = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import android.graphics.Bitmap
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import org.groundplatform.domain.model.geometry.Coordinates
import org.groundplatform.domain.model.geometry.Point
import org.groundplatform.feature.pdf.model.SubmissionPdfDocument
import org.groundplatform.feature.pdf.render.image.PdfImage
import org.groundplatform.feature.pdf.render.image.PdfImageSet
Expand Down Expand Up @@ -98,9 +100,26 @@ class PdfWriterTest {
fun `draws the submission title above the table with the job below it`() {
val canvas = renderDocument(SINGLE_PAGE_DOCUMENT)

val jobLineIndex = canvas.drawnText.indexOf("${TABLE.jobLabel}: ${TABLE.jobName}")
val jobLineIndex = canvas.drawnText.indexOf(JOB_LINE)
assertTrue(jobLineIndex > 0)
assertEquals("${TABLE.submissionLabel}: ${TABLE.loiName}", canvas.drawnText[jobLineIndex - 1])
assertEquals(SUBMISSION_LINE, canvas.drawnText[jobLineIndex - 1])
}

@Test
fun `draws the area between the submission title and the job line`() {
val canvas = renderDocument(SINGLE_PAGE_DOCUMENT.copy(mapBlock = MAP_BLOCK))

val areaLineIndex = canvas.drawnText.indexOf(AREA_LINE)
assertTrue(areaLineIndex > 0)
assertEquals(SUBMISSION_LINE, canvas.drawnText[areaLineIndex - 1])
assertEquals(JOB_LINE, canvas.drawnText[areaLineIndex + 1])
}

@Test
fun `draws no area line when the document has no area`() {
val canvas = renderDocument(SINGLE_PAGE_DOCUMENT.copy(mapBlock = MAP_BLOCK.copy(area = null)))

assertFalse(canvas.drawnText.any { it.startsWith(AREA.label) })
}

@Test
Expand Down Expand Up @@ -224,7 +243,7 @@ class PdfWriterTest {
val canvas = renderDocument(tableless, pdfImageSet(qr = pdfImage()))

assertEquals(listOf(1), canvas.startedPageNumbers)
assertFalse(canvas.drawnText.contains("${TABLE.submissionLabel}: ${TABLE.loiName}"))
assertFalse(canvas.drawnText.contains(SUBMISSION_LINE))
}

private fun renderDocument(
Expand Down Expand Up @@ -292,6 +311,15 @@ class PdfWriterTest {

val QR_BLOCK = SubmissionPdfDocument.QrBlock(submissionName = "Plot 42", scanCaption = "Scan")

val AREA = SubmissionPdfDocument.Area(label = "Area", value = "1.00 ha")

val MAP_BLOCK =
SubmissionPdfDocument.MapBlock(
geometry = Point(Coordinates(0.0, 0.0)),
style = null,
area = AREA,
)

val TABLE =
SubmissionPdfDocument.Table(
submissionLabel = "Submission",
Expand All @@ -301,6 +329,10 @@ class PdfWriterTest {
rows = emptyList(),
)

val SUBMISSION_LINE = "${TABLE.submissionLabel}: ${TABLE.loiName}"
val AREA_LINE = "${AREA.label}: ${AREA.value}"
val JOB_LINE = "${TABLE.jobLabel}: ${TABLE.jobName}"

val EMPTY_DOCUMENT =
SubmissionPdfDocument(
header = HEADER,
Expand Down
Loading