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 @@ -35,4 +35,5 @@
<string name="pdf_data_collector">Recolector de datos</string>
<string name="retry">Reintentar</string>
<string name="area">Área</string>
<string name="date">Fecha</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
<string name="pdf_data_collector">Collecteur de données</string>
<string name="retry">Réessayer</string>
<string name="area">Surface</string>
<string name="date">Date</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
<string name="pdf_data_collector">អ្នកប្រមូលទិន្នន័យ</string>
<string name="retry">ព្យាយាមឡើងវិញ</string>
<string name="area">ផ្ទៃក្រឡា</string>
<string name="date">កាលបរិច្ឆេទ</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
<string name="pdf_data_collector">ຜູ້ເກັບຂໍ້ມູນ</string>
<string name="retry">ລອງໃໝ່</string>
<string name="area">ພື້ນທີ່</string>
<string name="date">ວັນທີ</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@
<string name="pdf_data_collector">Coletor de dados</string>
<string name="retry">Tentar novamente</string>
<string name="area">Área</string>
<string name="date">Data</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
<string name="pdf_data_collector">ผู้เก็บข้อมูล</string>
<string name="retry">ลองใหม่</string>
<string name="area">พื้นที่</string>
<string name="date">วันที่</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
<string name="pdf_data_collector">Người thu thập dữ liệu</string>
<string name="retry">Thử lại</string>
<string name="area">Diện tích</string>
<string name="date">Ngày</string>
</resources>
1 change: 1 addition & 0 deletions core/ui/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@
<string name="pdf_data_collector">Data collector</string>
<string name="retry">Retry</string>
<string name="area">Area</string>
<string name="date">Date</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,21 @@ class PdfWriterTest {
}

@Test
fun `draws the header values on the page`() {
fun `draws the survey, submission and date columns in the header`() {
val canvas = renderDocument(SINGLE_PAGE_DOCUMENT)

assertTrue(canvas.drawnText.contains(HEADER.surveyName))
assertTrue(canvas.drawnText.contains(HEADER.jobName))
assertTrue(canvas.drawnText.contains(HEADER.timestamp))
assertTrue(canvas.drawnText.containsAll(listOf(HEADER.surveyLabel, HEADER.surveyName)))
assertTrue(canvas.drawnText.containsAll(listOf(HEADER.submissionLabel, HEADER.submissionName)))
assertTrue(canvas.drawnText.containsAll(listOf(HEADER.dateLabel, HEADER.timestamp)))
}

@Test
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}")
assertTrue(jobLineIndex > 0)
assertEquals("${TABLE.submissionLabel}: ${TABLE.loiName}", canvas.drawnText[jobLineIndex - 1])
}

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

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

private fun renderDocument(
Expand Down Expand Up @@ -269,8 +278,9 @@ class PdfWriterTest {
SubmissionPdfDocument.Header(
surveyLabel = "Survey",
surveyName = "Survey name",
jobLabel = "Job",
jobName = "Job name",
submissionLabel = "Submission",
submissionName = "Submission name",
dateLabel = "Date",
timestamp = "timestamp",
)
val FOOTER =
Expand All @@ -285,7 +295,9 @@ class PdfWriterTest {
val TABLE =
SubmissionPdfDocument.Table(
submissionLabel = "Submission",
loiName = "Plot 42",
loiName = "Submission name",
jobLabel = "Job",
jobName = "Job name",
rows = emptyList(),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import org.groundplatform.feature.pdf.render.PdfConfig.CAPTION_SIZE
import org.groundplatform.feature.pdf.render.PdfConfig.TITLE_SIZE

internal class PdfTextPaints {
val title: TextPaint = textPaint(TITLE_SIZE, bold = false)
val title: TextPaint = textPaint(TITLE_SIZE, bold = true)
val body: TextPaint = textPaint(BODY_SIZE, bold = false)
val bodyLabel: TextPaint = textPaint(BODY_SIZE, bold = true)
val metaLabel: TextPaint = textPaint(CAPTION_SIZE, bold = true, textColor = Color.GRAY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,19 @@ internal class PdfWriter(
private fun drawTable(table: SubmissionPdfDocument.Table) {
val rows = table.rows.takeIf { it.isNotEmpty() } ?: return
pageController.ensurePage()
val label =
SpannableString("${table.submissionLabel}: ${table.loiName}").apply {
setSpan(
StyleSpan(Typeface.BOLD),
0,
table.submissionLabel.length,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE,
)
}
val labelLayout = staticLayout(label, paints.title, USABLE_WIDTH)
val tableLabel =
TableLayout.getLabel(top = cursor.y, labelHeight = labelLayout.height.toFloat())
drawStaticLayoutAt(labelLayout, tableLabel.labelOffset)
cursor.moveTo(tableLabel.nextCursorY)
val titleLayout =
staticLayout("${table.submissionLabel}: ${table.loiName}", paints.title, USABLE_WIDTH)
val subtitleLayout =
staticLayout(labeled(table.jobLabel, table.jobName), paints.body, USABLE_WIDTH)
val titleBlock =
TableLayout.getTitleBlock(
top = cursor.y,
titleHeight = titleLayout.height.toFloat(),
subtitleHeight = subtitleLayout.height.toFloat(),
)
drawStaticLayoutAt(titleLayout, titleBlock.titleOffset)
drawStaticLayoutAt(subtitleLayout, titleBlock.subtitleOffset)
cursor.moveTo(titleBlock.nextCursorY)
rows.forEach { row ->
when (val answer = row.answer) {
is Answer.Text ->
Expand Down Expand Up @@ -154,16 +153,28 @@ internal class PdfWriter(
maxWidth = columnWidth,
maxLines = PageHeaderLayout.MAX_LINES,
)
val jobLabel =
staticLayout(header.jobLabel, paints.metaLabel, columnWidth, Layout.Alignment.ALIGN_CENTER)
val jobValue =
val submissionLabel =
staticLayout(
header.submissionLabel,
paints.metaLabel,
columnWidth,
Layout.Alignment.ALIGN_CENTER,
)
val submissionValue =
staticLayout(
text = header.jobName,
text = header.submissionName,
paint = paints.meta,
maxWidth = columnWidth,
alignment = Layout.Alignment.ALIGN_CENTER,
maxLines = PageHeaderLayout.MAX_LINES,
)
val dateLabel =
staticLayout(
header.dateLabel,
paints.metaLabel,
columnWidth,
Layout.Alignment.ALIGN_OPPOSITE,
)
val timestamp =
staticLayout(
text = header.timestamp,
Expand All @@ -182,9 +193,10 @@ internal class PdfWriter(

drawStaticLayoutAt(surveyLabel, layout.leftColumn.labelOffset)
drawStaticLayoutAt(surveyValue, layout.leftColumn.valueOffset)
drawStaticLayoutAt(jobLabel, layout.centerColumn.labelOffset)
drawStaticLayoutAt(jobValue, layout.centerColumn.valueOffset)
drawStaticLayoutAt(timestamp, layout.rightTextOffset)
drawStaticLayoutAt(submissionLabel, layout.centerColumn.labelOffset)
drawStaticLayoutAt(submissionValue, layout.centerColumn.valueOffset)
drawStaticLayoutAt(dateLabel, layout.rightColumn.labelOffset)
drawStaticLayoutAt(timestamp, layout.rightColumn.valueOffset)
cursor.moveTo(layout.nextCursorY)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package org.groundplatform.feature.pdf.mapper

import ground_android.core.ui.generated.resources.Res
import ground_android.core.ui.generated.resources.area
import ground_android.core.ui.generated.resources.date
import ground_android.core.ui.generated.resources.job
import ground_android.core.ui.generated.resources.pdf_data_collector
import ground_android.core.ui.generated.resources.scan_this_qr_to_download_geojson
Expand Down Expand Up @@ -51,13 +52,15 @@ class LoiReportMapper(
val rows = buildRows(submission)
val document =
SubmissionPdfDocument(
header = buildHeader(details, submission),
header = buildHeader(details, loiReport.loiName, submission),
qrBlock = buildQrBlock(loiReport.loiName),
footer = buildFooter(details),
table =
Table(
submissionLabel = strings.resolve(Res.string.submission),
loiName = loiReport.loiName,
jobLabel = strings.resolve(Res.string.job),
jobName = submission.jobName(),
rows = rows,
),
mapBlock = buildMapBlock(details),
Expand All @@ -81,18 +84,22 @@ class LoiReportMapper(

private suspend fun buildHeader(
details: LoiReport.SubmissionDetails,
loiName: String,
submission: Submission,
): Header =
Header(
surveyLabel = strings.resolve(Res.string.survey),
surveyName = details.surveyName,
jobLabel = strings.resolve(Res.string.job),
jobName = submission.job.name ?: submission.job.id,
submissionLabel = strings.resolve(Res.string.submission),
submissionName = loiName,
dateLabel = strings.resolve(Res.string.date),
timestamp =
"${dateFormatter.formatDate(submission.lastModified.clientTimestamp)} " +
dateFormatter.formatTime(submission.lastModified.clientTimestamp),
)

private fun Submission.jobName(): String = job.name ?: job.id

private suspend fun buildQrBlock(loiName: String): QrBlock =
QrBlock(
submissionName = loiName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,21 @@ data class SubmissionPdfDocument(
data class Header(
val surveyLabel: String,
val surveyName: String,
val jobLabel: String,
val jobName: String,
val submissionLabel: String,
val submissionName: String,
val dateLabel: String,
val timestamp: String,
)

data class QrBlock(val submissionName: String, val scanCaption: String)

data class Table(val submissionLabel: String, val loiName: String, val rows: List<Row>)
data class Table(
val submissionLabel: String,
val loiName: String,
val jobLabel: String,
val jobName: String,
val rows: List<Row>,
)

data class Row(val question: String, val answer: Answer)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ internal object PdfConfig {
const val MARGIN = 40

/** Font size for title text. */
const val TITLE_SIZE = 11f
const val TITLE_SIZE = 13f

/** Font size body and table-cell text. */
const val BODY_SIZE = 11f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import org.groundplatform.feature.pdf.render.PdfOffset
*
* @param leftColumn Label and value positions for the left column.
* @param centerColumn Label and value positions for the center column.
* @param rightTextOffset The position where the right-aligned value begins .
* @param rightColumn Label and value positions for the right column, whose text is right-aligned.
* @param nextCursorY The Y position where the cursor should be positioned after the header.
*/
internal data class PageHeaderLayout(
val leftColumn: Column,
val centerColumn: Column,
val rightTextOffset: PdfOffset,
val rightColumn: Column,
val nextCursorY: Float,
) {
companion object {
Expand All @@ -53,7 +53,7 @@ internal data class PageHeaderLayout(
return PageHeaderLayout(
leftColumn = column(LEFT_X, top, labelHeight),
centerColumn = column(CENTER_X, top, labelHeight),
rightTextOffset = PdfOffset(RIGHT_X, top),
rightColumn = column(RIGHT_X, top, labelHeight),
nextCursorY = columnBottom + BOTTOM_GAP,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,26 @@ internal object TableLayout {
)
}

data class Label(val labelOffset: PdfOffset, val nextCursorY: Float)

fun getLabel(top: Float, labelHeight: Float): Label {
val labelTop = top + LINE_SPACING * 2
return Label(
labelOffset = PdfOffset(MARGIN.toFloat(), labelTop),
nextCursorY = labelTop + labelHeight + LINE_SPACING,
/**
* Layout of the two title lines above the table.
*
* @param titleOffset Top-left position of the submission line.
* @param subtitleOffset Top-left position of the job line, directly below the submission line.
* @param nextCursorY Cursor Y position after the title block.
*/
data class TitleBlock(
val titleOffset: PdfOffset,
val subtitleOffset: PdfOffset,
val nextCursorY: Float,
)

fun getTitleBlock(top: Float, titleHeight: Float, subtitleHeight: Float): TitleBlock {
val titleTop = top + LINE_SPACING * 2
val subtitleTop = titleTop + titleHeight + LINE_SPACING
return TitleBlock(
titleOffset = PdfOffset(MARGIN.toFloat(), titleTop),
subtitleOffset = PdfOffset(MARGIN.toFloat(), subtitleTop),
nextCursorY = subtitleTop + subtitleHeight + LINE_SPACING * 2,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ class PdfExportServiceTest {
SubmissionPdfDocument.Header(
surveyLabel = "Survey",
surveyName = "Survey name",
jobLabel = "Job",
jobName = "Job name",
submissionLabel = "Submission",
submissionName = "Loi",
dateLabel = "Date",
timestamp = "timestamp",
),
qrBlock = SubmissionPdfDocument.QrBlock(submissionName = "Loi", scanCaption = "Scan"),
Expand All @@ -119,6 +120,8 @@ class PdfExportServiceTest {
SubmissionPdfDocument.Table(
submissionLabel = "Submission",
loiName = "Loi",
jobLabel = "Job",
jobName = "Job name",
rows = emptyList(),
),
mapBlock = null,
Expand Down
Loading
Loading