feat: update field type handling and add multi-select support
This commit is contained in:
@@ -47,6 +47,9 @@ interface FieldDao {
|
||||
@Query("SELECT * FROM fields WHERE updatedAt >= :since")
|
||||
suspend fun getFieldsUpdatedSince(since: Long): List<Field>
|
||||
|
||||
@Query("UPDATE fields SET `order` = :newOrder, updatedAt = :timestamp WHERE id = :fieldId")
|
||||
suspend fun updateFieldOrder(fieldId: String, newOrder: Int, timestamp: Long)
|
||||
|
||||
// Reorder fields in a single transaction for clarity and consistency
|
||||
@Transaction
|
||||
suspend fun reorderFieldsInTransaction(
|
||||
@@ -54,12 +57,7 @@ interface FieldDao {
|
||||
timestamp: Long,
|
||||
) {
|
||||
reorderedFields.forEachIndexed { index, field ->
|
||||
updateField(
|
||||
field.copy(
|
||||
order = index,
|
||||
updatedAt = timestamp,
|
||||
),
|
||||
)
|
||||
updateFieldOrder(field.id, index, timestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ enum class FieldType {
|
||||
PERCENTAGE,
|
||||
|
||||
// Selection types
|
||||
DROPDOWN,
|
||||
SELECT,
|
||||
MULTI_SELECT,
|
||||
AUTOCOMPLETE,
|
||||
CHECKBOX,
|
||||
SWITCH,
|
||||
@@ -77,6 +78,7 @@ data class Field(
|
||||
} catch (e: Exception) {
|
||||
// Handle legacy/synonym field types
|
||||
when (raw) {
|
||||
"DROPDOWN" -> FieldType.SELECT
|
||||
"STRING" -> FieldType.TEXT
|
||||
"PRICE" -> FieldType.CURRENCY
|
||||
"AMOUNT" -> FieldType.NUMBER
|
||||
@@ -86,8 +88,8 @@ data class Field(
|
||||
}
|
||||
}
|
||||
|
||||
fun getDropdownOptions(): List<String> =
|
||||
if (getType() == FieldType.DROPDOWN && fieldOptions.isNotBlank()) {
|
||||
fun getSelectOptions(): List<String> =
|
||||
if ((getType() == FieldType.SELECT || getType() == FieldType.MULTI_SELECT) && fieldOptions.isNotBlank()) {
|
||||
fieldOptions.split("|")
|
||||
} else {
|
||||
emptyList()
|
||||
|
||||
+102
-21
@@ -804,7 +804,8 @@ private fun getDisplayTextForMeasure(
|
||||
com.collabtable.app.data.model.FieldType.TEXT,
|
||||
com.collabtable.app.data.model.FieldType.MULTILINE_TEXT,
|
||||
com.collabtable.app.data.model.FieldType.NUMBER,
|
||||
com.collabtable.app.data.model.FieldType.DROPDOWN,
|
||||
com.collabtable.app.data.model.FieldType.SELECT,
|
||||
com.collabtable.app.data.model.FieldType.MULTI_SELECT,
|
||||
com.collabtable.app.data.model.FieldType.AUTOCOMPLETE,
|
||||
com.collabtable.app.data.model.FieldType.DURATION,
|
||||
com.collabtable.app.data.model.FieldType.LOCATION,
|
||||
@@ -848,7 +849,8 @@ private fun fieldTypeToLabel(type: String): String =
|
||||
"NUMBER" -> "Number"
|
||||
"CURRENCY", "PRICE" -> "Currency"
|
||||
"PERCENTAGE" -> "Percentage"
|
||||
"DROPDOWN" -> "Dropdown"
|
||||
"SELECT", "Select" -> "Select"
|
||||
"MULTI_SELECT" -> "Multi-select"
|
||||
"AUTOCOMPLETE" -> "Autocomplete"
|
||||
"CHECKBOX" -> "Checkbox"
|
||||
"SWITCH" -> "Switch"
|
||||
@@ -1102,7 +1104,8 @@ fun ItemRow(
|
||||
)
|
||||
}
|
||||
|
||||
com.collabtable.app.data.model.FieldType.DROPDOWN -> {
|
||||
com.collabtable.app.data.model.FieldType.SELECT,
|
||||
com.collabtable.app.data.model.FieldType.MULTI_SELECT -> {
|
||||
Text(
|
||||
text = value?.value ?: "",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
@@ -1576,9 +1579,16 @@ fun AddFieldDialog(
|
||||
|
||||
// Selection types
|
||||
DropdownMenuItem(
|
||||
text = { Text("Dropdown") },
|
||||
text = { Text("Select") },
|
||||
onClick = {
|
||||
selectedFieldType = "DROPDOWN"
|
||||
selectedFieldType = "SELECT"
|
||||
expanded = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Multi-select") },
|
||||
onClick = {
|
||||
selectedFieldType = "MULTI_SELECT"
|
||||
expanded = false
|
||||
},
|
||||
)
|
||||
@@ -1725,14 +1735,14 @@ fun AddFieldDialog(
|
||||
}
|
||||
|
||||
// Dropdown-specific options
|
||||
if (selectedFieldType == "DROPDOWN") {
|
||||
if (selectedFieldType == "SELECT" || selectedFieldType == "MULTI_SELECT") {
|
||||
OutlinedTextField(
|
||||
value = dropdownOptions,
|
||||
onValueChange = { dropdownOptions = it },
|
||||
label = { Text("Options (comma-separated)") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = { Text("Option 1, Option 2, Option 3") },
|
||||
supportingText = { Text("Enter dropdown choices separated by commas") },
|
||||
supportingText = { Text("Enter select choices separated by commas") },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1770,7 +1780,7 @@ fun AddFieldDialog(
|
||||
val options =
|
||||
when (normalizedType) {
|
||||
"CURRENCY" -> currency.trim()
|
||||
"DROPDOWN" ->
|
||||
"SELECT", "MULTI_SELECT" ->
|
||||
dropdownOptions
|
||||
.split(",")
|
||||
.map { it.trim() }
|
||||
@@ -1790,7 +1800,7 @@ fun AddFieldDialog(
|
||||
},
|
||||
enabled =
|
||||
fieldName.isNotBlank() &&
|
||||
(selectedFieldType.uppercase() !in listOf("DROPDOWN", "AUTOCOMPLETE") || dropdownOptions.isNotBlank()),
|
||||
(selectedFieldType.uppercase() !in listOf("SELECT", "MULTI_SELECT", "AUTOCOMPLETE") || dropdownOptions.isNotBlank()),
|
||||
) {
|
||||
Text(stringResource(R.string.add))
|
||||
}
|
||||
@@ -1812,7 +1822,7 @@ fun EditFieldDialog(
|
||||
) {
|
||||
var name by remember { mutableStateOf(field.name) }
|
||||
var selectedFieldType by remember { mutableStateOf(field.fieldType.uppercase()) }
|
||||
var dropdownOptions by remember { mutableStateOf(field.getDropdownOptions().joinToString(", ")) }
|
||||
var dropdownOptions by remember { mutableStateOf(field.getSelectOptions().joinToString(", ")) }
|
||||
var currency by remember { mutableStateOf(field.getCurrency()) }
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
// Alignment state persisted per list/field in PreferencesManager
|
||||
@@ -1902,9 +1912,16 @@ fun EditFieldDialog(
|
||||
|
||||
// Selection types
|
||||
DropdownMenuItem(
|
||||
text = { Text("Dropdown") },
|
||||
text = { Text("Select") },
|
||||
onClick = {
|
||||
selectedFieldType = "DROPDOWN"
|
||||
selectedFieldType = "SELECT"
|
||||
expanded = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Multi-select") },
|
||||
onClick = {
|
||||
selectedFieldType = "MULTI_SELECT"
|
||||
expanded = false
|
||||
},
|
||||
)
|
||||
@@ -2051,14 +2068,14 @@ fun EditFieldDialog(
|
||||
}
|
||||
|
||||
// Dropdown-specific options
|
||||
if (selectedFieldType == "DROPDOWN") {
|
||||
if (selectedFieldType == "SELECT" || selectedFieldType == "MULTI_SELECT") {
|
||||
OutlinedTextField(
|
||||
value = dropdownOptions,
|
||||
onValueChange = { dropdownOptions = it },
|
||||
label = { Text("Options (comma-separated)") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = { Text("Option 1, Option 2, Option 3") },
|
||||
supportingText = { Text("Enter dropdown choices separated by commas") },
|
||||
supportingText = { Text("Enter select choices separated by commas") },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2113,7 +2130,7 @@ fun EditFieldDialog(
|
||||
val options =
|
||||
when (normalizedType) {
|
||||
"CURRENCY", "PRICE" -> currency.trim()
|
||||
"DROPDOWN" ->
|
||||
"SELECT", "MULTI_SELECT" ->
|
||||
dropdownOptions
|
||||
.split(",")
|
||||
.map { it.trim() }
|
||||
@@ -2139,7 +2156,7 @@ fun EditFieldDialog(
|
||||
}
|
||||
prefs.setColumnAlignments(field.listId, current)
|
||||
},
|
||||
enabled = name.isNotBlank() && (selectedFieldType !in listOf("DROPDOWN", "AUTOCOMPLETE") || dropdownOptions.isNotBlank()),
|
||||
enabled = name.isNotBlank() && (selectedFieldType !in listOf("SELECT", "MULTI_SELECT", "AUTOCOMPLETE") || dropdownOptions.isNotBlank()),
|
||||
) {
|
||||
Text("Update")
|
||||
}
|
||||
@@ -2306,9 +2323,9 @@ fun FieldInput(
|
||||
}
|
||||
}
|
||||
|
||||
com.collabtable.app.data.model.FieldType.DROPDOWN -> {
|
||||
val options = field.getDropdownOptions()
|
||||
var dropdownExpanded by remember { mutableStateOf(false) }
|
||||
com.collabtable.app.data.model.FieldType.SELECT -> {
|
||||
val options = field.getSelectOptions()
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
ExposedDropdownMenuBox(
|
||||
expanded = dropdownExpanded,
|
||||
@@ -2345,6 +2362,60 @@ fun FieldInput(
|
||||
}
|
||||
}
|
||||
|
||||
com.collabtable.app.data.model.FieldType.MULTI_SELECT -> {
|
||||
val options = field.getSelectOptions()
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val selectedOptions = remember(value) {
|
||||
value.split(", ").filter { it.isNotBlank() }.toSet()
|
||||
}
|
||||
|
||||
ExposedDropdownMenuBox(
|
||||
expanded = dropdownExpanded,
|
||||
onExpandedChange = { dropdownExpanded = !dropdownExpanded },
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
label = { Text(field.name) },
|
||||
trailingIcon = {
|
||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = dropdownExpanded)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.menuAnchor()
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
||||
ExposedDropdownMenu(
|
||||
expanded = dropdownExpanded,
|
||||
onDismissRequest = { dropdownExpanded = false },
|
||||
) {
|
||||
options.forEach { option ->
|
||||
val isSelected = selectedOptions.contains(option)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Checkbox(checked = isSelected, onCheckedChange = null)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(option)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
val newSelected = if (isSelected) {
|
||||
selectedOptions - option
|
||||
} else {
|
||||
selectedOptions + option
|
||||
}
|
||||
val orderedNewSelected = options.filter { it in newSelected }
|
||||
onValueChange(orderedNewSelected.joinToString(", "))
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
com.collabtable.app.data.model.FieldType.URL -> {
|
||||
OutlinedTextField(
|
||||
value = value,
|
||||
@@ -3070,8 +3141,10 @@ fun ColumnItem(
|
||||
// Selection types
|
||||
com.collabtable.app.data.model.FieldType.CHECKBOX -> "Checkbox"
|
||||
com.collabtable.app.data.model.FieldType.SWITCH -> "Switch"
|
||||
com.collabtable.app.data.model.FieldType.DROPDOWN ->
|
||||
"Dropdown (${field.getDropdownOptions().size} options)"
|
||||
com.collabtable.app.data.model.FieldType.SELECT ->
|
||||
"Select (${field.getSelectOptions().size} options)"
|
||||
com.collabtable.app.data.model.FieldType.MULTI_SELECT ->
|
||||
"Multi-select (${field.getSelectOptions().size} options)"
|
||||
com.collabtable.app.data.model.FieldType.AUTOCOMPLETE ->
|
||||
"Autocomplete (${field.getAutocompleteOptions().size} options)"
|
||||
|
||||
@@ -4011,3 +4084,11 @@ private fun RenameListDialog(
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user