load selectValues from Tags-endpoint

This commit is contained in:
Thomas Boksberger committed 2026-04-07 07:56:38 +02:00
1 parent 2434383953
commit af0d8b77a5
7 files changed
+47 -27

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.nbadal.ktlint.KtlintProjectSettings">
<ktlintRulesetVersion>DEFAULT</ktlintRulesetVersion>
</component>
</project>
+5
View File
@@ -27,6 +27,11 @@ GET http://localhost:31009/v1/spaces/{{spaceId}}/properties/{{priorityPropertyId
Authorization: Bearer {{apiKey}} Authorization: Bearer {{apiKey}}
Anytype-Version: 0.1 Anytype-Version: 0.1
### Get Property Tags
GET http://localhost:31009/v1/spaces/{{spaceId}}/properties/{{priorityPropertyId}}/tags
Authorization: Bearer {{apiKey}}
Anytype-Version: 0.1
### Get Templates ### Get Templates
GET http://localhost:31009/v1/spaces/{{spaceId}}/types/{{taskTypeId}}/templates GET http://localhost:31009/v1/spaces/{{spaceId}}/types/{{taskTypeId}}/templates
Authorization: Bearer {{apiKey}} Authorization: Bearer {{apiKey}}
+1 -1
View File
@@ -152,7 +152,7 @@ private fun setupSystemTray(onShow: () -> Unit, onSettings: () -> Unit, onExit:
val icon = createTrayIcon(size) val icon = createTrayIcon(size)
val menu = PopupMenu().apply { val menu = PopupMenu().apply {
add(MenuItem("Open").also { it.addActionListener { onShow() } }) add(MenuItem("Create Task").also { it.addActionListener { onShow() } })
add(MenuItem("Settings").also { it.addActionListener { onSettings() } }) add(MenuItem("Settings").also { it.addActionListener { onSettings() } })
addSeparator() addSeparator()
add(MenuItem("Quit").also { it.addActionListener { onExit() } }) add(MenuItem("Quit").also { it.addActionListener { onExit() } })
@@ -88,6 +88,15 @@ class AnyTypeApi(
response.body<SearchObjectsResponse>().data response.body<SearchObjectsResponse>().data
} }
suspend fun getTags(propertyId: String): Result<List<Tag>> =
runCatching {
val response = http.get("$baseUrl/v1/spaces/$spaceId/properties/$propertyId/tags") {
header("Anytype-Version", "2025-11-08")
bearerAuth(apiKey)
}
response.body<TagsResponse>().data
}
suspend fun getTemplates(typeId: String): Result<List<Template>> = suspend fun getTemplates(typeId: String): Result<List<Template>> =
runCatching { runCatching {
val response = http.get("$baseUrl/v1/spaces/$spaceId/types/$typeId/templates") { val response = http.get("$baseUrl/v1/spaces/$spaceId/types/$typeId/templates") {
@@ -17,10 +17,10 @@ data class Connection(
@Serializable @Serializable
data class PropertyConfig( data class PropertyConfig(
val key: String, val key: String,
val id: String = "",
val name: String = "", val name: String = "",
val format: String = "", val format: String = "",
val indicator: String = "", val indicator: String = "",
@SerialName("possible_values") val possibleValues: List<String> = emptyList(),
@SerialName("object_type_key") val objectTypeKey: String = "", @SerialName("object_type_key") val objectTypeKey: String = "",
) )
@@ -364,7 +364,6 @@ private fun PropertyTable(
Text("Name", fontWeight = FontWeight.Bold, modifier = Modifier.weight(2f)) Text("Name", fontWeight = FontWeight.Bold, modifier = Modifier.weight(2f))
Text("Type", fontWeight = FontWeight.Bold, modifier = Modifier.weight(1.5f)) Text("Type", fontWeight = FontWeight.Bold, modifier = Modifier.weight(1.5f))
Text("Ind.", fontWeight = FontWeight.Bold, modifier = Modifier.weight(0.7f)) Text("Ind.", fontWeight = FontWeight.Bold, modifier = Modifier.weight(0.7f))
Text("Values", fontWeight = FontWeight.Bold, modifier = Modifier.weight(2f))
Text("Obj Type", fontWeight = FontWeight.Bold, modifier = Modifier.weight(1.5f)) Text("Obj Type", fontWeight = FontWeight.Bold, modifier = Modifier.weight(1.5f))
Spacer(modifier = Modifier.width(40.dp)) Spacer(modifier = Modifier.width(40.dp))
} }
@@ -383,11 +382,6 @@ private fun PropertyTable(
Text(prop.name, modifier = Modifier.weight(2f), maxLines = 1) Text(prop.name, modifier = Modifier.weight(2f), maxLines = 1)
Text(prop.format, modifier = Modifier.weight(1.5f), maxLines = 1) Text(prop.format, modifier = Modifier.weight(1.5f), maxLines = 1)
Text(prop.indicator, modifier = Modifier.weight(0.7f), maxLines = 1) Text(prop.indicator, modifier = Modifier.weight(0.7f), maxLines = 1)
Text(
prop.possibleValues.joinToString(", "),
modifier = Modifier.weight(2f),
maxLines = 1,
)
Text(prop.objectTypeKey, modifier = Modifier.weight(1.5f), maxLines = 1) Text(prop.objectTypeKey, modifier = Modifier.weight(1.5f), maxLines = 1)
IconButton(onClick = { onDelete(index) }) { IconButton(onClick = { onDelete(index) }) {
Icon(Icons.Default.Delete, contentDescription = "Delete", tint = Color.Gray) Icon(Icons.Default.Delete, contentDescription = "Delete", tint = Color.Gray)
@@ -409,7 +403,6 @@ private fun PropertyEditPanel(
) { ) {
var selectedPropertyKey by remember(existing) { mutableStateOf(existing?.key ?: "") } var selectedPropertyKey by remember(existing) { mutableStateOf(existing?.key ?: "") }
var indicator by remember(existing) { mutableStateOf(existing?.indicator ?: "") } var indicator by remember(existing) { mutableStateOf(existing?.indicator ?: "") }
var possibleValuesText by remember(existing) { mutableStateOf(existing?.possibleValues?.joinToString("\n") ?: "") }
var objectTypeKey by remember(existing) { mutableStateOf(existing?.objectTypeKey ?: "") } var objectTypeKey by remember(existing) { mutableStateOf(existing?.objectTypeKey ?: "") }
val selectedProperty = availableProperties.find { it.key == selectedPropertyKey } val selectedProperty = availableProperties.find { it.key == selectedPropertyKey }
@@ -446,15 +439,6 @@ private fun PropertyEditPanel(
// Format-specific fields // Format-specific fields
when (format) { when (format) {
"select", "multi_select" -> {
OutlinedTextField(
value = possibleValuesText,
onValueChange = { possibleValuesText = it },
label = { Text("Possible Values (one per line)") },
modifier = Modifier.fillMaxWidth().height(120.dp),
maxLines = 10,
)
}
"object", "objects" -> { "object", "objects" -> {
DropdownSelector( DropdownSelector(
label = "Object Type", label = "Object Type",
@@ -470,14 +454,13 @@ private fun PropertyEditPanel(
TextButton(onClick = onCancel) { Text("Cancel") } TextButton(onClick = onCancel) { Text("Cancel") }
Button( Button(
onClick = { onClick = {
val values = possibleValuesText.lines().map { it.trim() }.filter { it.isNotEmpty() }
onConfirm( onConfirm(
PropertyConfig( PropertyConfig(
key = selectedPropertyKey, key = selectedPropertyKey,
id = selectedProperty?.id ?: existing?.id ?: "",
name = selectedProperty?.name ?: existing?.name ?: "", name = selectedProperty?.name ?: existing?.name ?: "",
format = format, format = format,
indicator = indicator, indicator = indicator,
possibleValues = values,
objectTypeKey = objectTypeKey, objectTypeKey = objectTypeKey,
) )
) )
@@ -49,6 +49,7 @@ import androidx.compose.ui.input.key.type
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ch.ergon.anytask.api.AnyTypeApi import ch.ergon.anytask.api.AnyTypeApi
import ch.ergon.anytask.api.dto.SearchObject import ch.ergon.anytask.api.dto.SearchObject
import ch.ergon.anytask.api.dto.Tag
import ch.ergon.anytask.config.Configuration import ch.ergon.anytask.config.Configuration
import ch.ergon.anytask.api.dto.buildPropertyValue import ch.ergon.anytask.api.dto.buildPropertyValue
import ch.ergon.anytask.config.PropertyConfig import ch.ergon.anytask.config.PropertyConfig
@@ -62,6 +63,7 @@ fun TaskWindow(client: AnyTypeApi, config: Configuration, isVisible: Boolean, on
var isLoading by remember { mutableStateOf(false) } var isLoading by remember { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf<String?>(null) } var errorMessage by remember { mutableStateOf<String?>(null) }
val propertyValues = remember { mutableStateMapOf<String, String>() } val propertyValues = remember { mutableStateMapOf<String, String>() }
val propertyTags = remember { mutableStateMapOf<String, List<Tag>>() }
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
@@ -144,6 +146,7 @@ fun TaskWindow(client: AnyTypeApi, config: Configuration, isVisible: Boolean, on
value = propertyValues[prop.key] ?: "", value = propertyValues[prop.key] ?: "",
onValueChange = { propertyValues[prop.key] = it }, onValueChange = { propertyValues[prop.key] = it },
client = client, client = client,
tags = propertyTags[prop.key] ?: emptyList(),
) )
} }
} }
@@ -174,7 +177,19 @@ fun TaskWindow(client: AnyTypeApi, config: Configuration, isVisible: Boolean, on
} }
} }
LaunchedEffect(isVisible) { if (isVisible) focusRequester.requestFocus() } LaunchedEffect(isVisible) {
if (isVisible) {
focusRequester.requestFocus()
config.properties
.filter { it.format in listOf("select", "multi_select") && it.id.isNotEmpty() }
.forEach { prop ->
launch {
client.getTags(prop.id)
.onSuccess { propertyTags[prop.key] = it }
}
}
}
}
} }
@Composable @Composable
@@ -183,13 +198,14 @@ private fun PropertyField(
value: String, value: String,
onValueChange: (String) -> Unit, onValueChange: (String) -> Unit,
client: AnyTypeApi, client: AnyTypeApi,
tags: List<Tag> = emptyList(),
) { ) {
when (prop.format) { when (prop.format) {
"select", "multi_select" -> { "select", "multi_select" -> {
SelectField( SelectField(
label = prop.name, label = prop.name,
value = value, value = value,
options = prop.possibleValues, tags = tags,
onValueChange = onValueChange, onValueChange = onValueChange,
) )
} }
@@ -231,16 +247,17 @@ private fun PropertyField(
private fun SelectField( private fun SelectField(
label: String, label: String,
value: String, value: String,
options: List<String>, tags: List<Tag>,
onValueChange: (String) -> Unit, onValueChange: (String) -> Unit,
) { ) {
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
val selectedName = tags.find { it.id == value }?.name ?: value
Column { Column {
Text(label, style = MaterialTheme.typography.caption) Text(label, style = MaterialTheme.typography.caption)
Box { Box {
OutlinedButton(onClick = { expanded = true }, modifier = Modifier.fillMaxWidth()) { OutlinedButton(onClick = { expanded = true }, modifier = Modifier.fillMaxWidth()) {
Text(value.ifEmpty { "Select..." }) Text(selectedName.ifEmpty { "Select..." })
} }
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
@@ -249,12 +266,12 @@ private fun SelectField(
}) { }) {
Text("(none)", style = MaterialTheme.typography.caption) Text("(none)", style = MaterialTheme.typography.caption)
} }
options.forEach { option -> tags.forEach { tag ->
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
onValueChange(option) onValueChange(tag.id)
expanded = false expanded = false
}) { }) {
Text(option) Text(tag.name)
} }
} }
} }
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.