Skip to content

Commit

Permalink
feat: [ANDROAPP-6693] initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
xavimolloy committed Dec 2, 2024
1 parent 64a1951 commit a1dc252
Show file tree
Hide file tree
Showing 62 changed files with 3,589 additions and 10 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
version = "0.4.1-SNAPSHOT"
version = "0.4.0.1-SNAPSHOTLOCAL"
group = "org.hisp.dhis.mobile"

plugins {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ publishing {
}

// Signing artifacts. Signing.* extra properties values will be used
signing {
setRequired({ !version.toString().endsWith("-SNAPSHOT") })
useInMemoryPgpKeys(signingPrivateKey, signingPassword)
sign(publishing.publications)
}
//signing {
// setRequired({ !version.toString().endsWith("-SNAPSHOT") })
// useInMemoryPgpKeys(signingPrivateKey, signingPassword)
// sign(publishing.publications)
//}

// Fix Gradle warning about signing tasks using publishing task outputs without explicit dependencies
// https://github.com/gradle/gradle/issues/26091
tasks.withType<AbstractPublishToMaven>().configureEach {
val signingTasks = tasks.withType<Sign>()
mustRunAfter(signingTasks)
}
//tasks.withType<AbstractPublishToMaven>().configureEach {
// val signingTasks = tasks.withType<Sign>()
// mustRunAfter(signingTasks)
//}
3 changes: 3 additions & 0 deletions designsystem/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {
id("org.jetbrains.compose")
id("com.android.library")
id("convention.publication")
id("org.jetbrains.kotlin.plugin.serialization").version("2.0.20")
id("app.cash.paparazzi").version("1.3.3")
alias(libs.plugins.compose.compiler)
}
Expand All @@ -29,6 +30,8 @@ kotlin {
api(compose.materialIconsExtended)
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.components.resources)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation("tech.annexflow.compose:constraintlayout-compose-multiplatform:0.4.0")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable

import org.hisp.dhis.mobile.ui.designsystem.component.composetable.model.TableModel
import java.util.UUID

data class TableScreenState(
val tables: List<TableModel>,
val id: UUID = UUID.randomUUID(),
val state: TableState = TableState.LOADING,
)
// todo review if this class is still needed
data class TableConfigurationState(
val overwrittenTableWidth: Map<String, Float>? = null,
val overwrittenRowHeaderWidth: Map<String, Float>? = null,
val overwrittenColumnWidth: Map<String, Map<Int, Float>>? = null,
) {
fun isResized() = !overwrittenTableWidth.isNullOrEmpty() or
!overwrittenRowHeaderWidth.isNullOrEmpty() or
!overwrittenColumnWidth.isNullOrEmpty()
}

enum class TableState {
LOADING,
SUCCESS,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.actions

class DefaultValidator : Validator
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.actions

import org.hisp.dhis.mobile.ui.designsystem.component.composetable.model.TableCell
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.model.TableDialogModel
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.ui.TableSelection

interface TableInteractions {
fun onSelectionChange(newTableSelection: TableSelection) = run { }
fun onDecorationClick(dialogModel: TableDialogModel) = run { }
fun onClick(tableCell: TableCell) = run { }
fun onOptionSelected(cell: TableCell, code: String, label: String) = run { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.actions

interface TableResizeActions {
fun onTableWidthChanged(width: Int) = run {}
fun onRowHeaderResize(tableId: String, newValue: Float) = run {}
fun onColumnHeaderResize(tableId: String, column: Int, newValue: Float) = run {}
fun onTableDimensionResize(tableId: String, newValue: Float) = run {}
fun onTableDimensionReset(tableId: String) = run {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.actions

import org.hisp.dhis.mobile.ui.designsystem.component.composetable.model.TextInputModel
// todo review whether this interface is still needed
interface TextInputInteractions {
fun onTextChanged(textInputModel: TextInputModel) = run {}
fun onSave() = run {}
fun onNextSelected() = run {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.actions

import org.hisp.dhis.mobile.ui.designsystem.component.composetable.model.TableCell
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.model.ValidationResult

interface Validator {
fun validate(tableCell: TableCell): ValidationResult {
return ValidationResult.Success(tableCell.value)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

//todo: maybe we could rethink this class in order to avoid using it in so many different places in the app, it could be a generic T variable
@Serializable
data class DropdownOption(
val code: String,
val name: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

data class HeaderMeasures(val width: Int, val height: Int)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import androidx.compose.foundation.layout.PaddingValues
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.ui.CellStyle
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.ui.TableDimensions
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.ui.semantics.HEADER_CELL

data class ItemColumnHeaderUiState(
val tableId: String?,
val rowIndex: Int,
val columnIndex: Int,
val headerCell: TableHeaderCell,
val headerMeasures: HeaderMeasures,
val paddingValues: PaddingValues,
val cellStyle: CellStyle,
val onCellSelected: (Int) -> Unit,
val onHeaderResize: (Int, Float) -> Unit,
val onResizing: (ResizingCell?) -> Unit,
val isLastRow: Boolean,
val checkMaxCondition: (TableDimensions, Float) -> Boolean,
) {
val testTag = "$HEADER_CELL$tableId$rowIndex$columnIndex"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import androidx.compose.ui.unit.Dp
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.ui.CellStyle

data class ItemHeaderUiState(
val tableId: String,
val rowHeader: RowHeader,
val cellStyle: CellStyle,
val width: Dp,
val maxLines: Int,
val onCellSelected: (Int?) -> Unit,
val onDecorationClick: (dialogModel: TableDialogModel) -> Unit,
val onHeaderResize: (Float) -> Unit,
val onResizing: (ResizingCell?) -> Unit,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

sealed class KeyboardInputType(
open val multiline: Boolean = false,
open val forceCapitalize: Boolean = false,
) {
data class TextInput(
override val multiline: Boolean = false,
override val forceCapitalize: Boolean = false,
) : KeyboardInputType(multiline, forceCapitalize)

data class NumericInput(
override val multiline: Boolean = false,
override val forceCapitalize: Boolean = false,
val allowDecimal: Boolean = true,
val allowSigned: Boolean = true,
) : KeyboardInputType(multiline, forceCapitalize)

data class NumberPassword(
override val multiline: Boolean = false,
override val forceCapitalize: Boolean = false,
) : KeyboardInputType(multiline, forceCapitalize)

data class PhoneInput(
override val multiline: Boolean = false,
override val forceCapitalize: Boolean = false,
) : KeyboardInputType(multiline)

data class EmailInput(
override val multiline: Boolean = false,
override val forceCapitalize: Boolean = false,
) : KeyboardInputType(multiline, forceCapitalize)

data class URLInput(
override val multiline: Boolean = false,
override val forceCapitalize: Boolean = false,
) : KeyboardInputType(multiline, forceCapitalize)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import androidx.compose.ui.geometry.Offset

data class ResizingCell(
val initialPosition: Offset,
val draggingOffsetX: Float,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

@Serializable
data class RowHeader(
val id: String? = null,
val title: String,
val row: Int,
val showDecoration: Boolean = false,
val description: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

@Serializable
data class TableCell(
val id: String? = null,
val row: Int? = null,
val column: Int,
val value: String?,
val editable: Boolean = true,
val mandatory: Boolean? = false,
val error: String? = null,
val warning: String? = null,
val legendColor: Int? = null,
val isMultiText: Boolean = false,
) {

fun hasErrorOrWarning() = errorOrWarningMessage() != null
fun errorOrWarningMessage() = error ?: warning
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

data class TableCornerUiState(
val isSelected: Boolean = false,
val onTableResize: (Float) -> Unit,
val onResizing: (ResizingCell?) -> Unit,
val singleValueTable: Boolean = false,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

data class TableDialogModel(
val title: String,
val message: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

@Serializable
data class TableHeader(val rows: List<TableHeaderRow>, val hasTotals: Boolean = false) {
fun numberOfColumns(rowIndex: Int): Int {
var totalCells = 1
for (index in 0 until rowIndex + 1) {
totalCells *= rows[index].cells.size
}
return totalCells
}

fun tableMaxColumns() = numberOfColumns(rows.size - 1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

@Serializable
data class TableHeaderCell(val value: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

@Serializable
data class TableHeaderRow(val cells: List<TableHeaderCell>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable
import org.hisp.dhis.mobile.ui.designsystem.component.composetable.ui.TableSelection

@Serializable
data class TableModel(
val id: String? = null,
val title: String = "",
val tableHeaderModel: TableHeader,
val tableRows: List<TableRowModel>,
val overwrittenValues: Map<Int, TableCell> = emptyMap(),
) {
fun countChildrenOfSelectedHeader(
headerRowIndex: Int,
headerColumnIndex: Int,
): Map<Int, TableSelection.HeaderCellRange> {
return tableHeaderModel.rows
.filterIndexed { index, _ -> index > headerRowIndex }
.mapIndexed { index, _ ->
val rowIndex = headerRowIndex + 1 + index
val rowSize =
tableHeaderModel.numberOfColumns(rowIndex) / tableHeaderModel.numberOfColumns(
headerRowIndex,
)
val init = headerColumnIndex * rowSize
val end = (headerColumnIndex + 1) * rowSize - 1
rowIndex to TableSelection.HeaderCellRange(rowSize, init, end)
}.toMap()
}

fun getNextCell(
cellSelection: TableSelection.CellSelection,
successValidation: Boolean,
): Pair<TableCell, TableSelection.CellSelection>? = when {
!successValidation ->
cellSelection
cellSelection.columnIndex < tableHeaderModel.tableMaxColumns() - 1 ->
cellSelection.copy(columnIndex = cellSelection.columnIndex + 1)
cellSelection.rowIndex < tableRows.size - 1 ->
cellSelection.copy(
columnIndex = 0,
rowIndex = cellSelection.rowIndex + 1,
globalIndex = cellSelection.globalIndex + 1,
)
else -> null
}?.let { nextCell ->
val tableCell = tableRows[nextCell.rowIndex].values[nextCell.columnIndex]
when (tableCell?.editable) {
true -> Pair(tableCell, nextCell)
else -> getNextCell(nextCell, successValidation)
}
}

fun cellHasError(cell: TableSelection.CellSelection): TableCell? {
return when {
tableRows.size == 1 && tableRows.size == cell.rowIndex -> {
tableRows[0].values[cell.columnIndex]?.takeIf { it.error != null }
}
tableRows.size == cell.rowIndex -> {
tableRows[cell.rowIndex - 1].values[cell.columnIndex]?.takeIf { it.error != null }
}
else -> tableRows[cell.rowIndex].values[cell.columnIndex]?.takeIf { it.error != null }
}
}

//review whether this class is still needed
fun hasCellWithId(cellId: String?): Boolean {
return tableRows.any { row ->
row.rowHeader.id?.let {
it.isNotEmpty() && cellId?.contains(it) == true
} ?: false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.hisp.dhis.mobile.ui.designsystem.component.composetable.model

import kotlinx.serialization.Serializable

@Serializable
data class TableRowModel(
val rowHeader: RowHeader,
val values: Map<Int, TableCell>,
val isLastRow: Boolean = false,
val maxLines: Int = 3,
val dropDownOptions: List<DropdownOption>? = null,
)
Loading

0 comments on commit a1dc252

Please sign in to comment.