load selectValues from Tags-endpoint
This commit is contained in:
1 parent
2434383953
commit
af0d8b77a5
7 files changed
+47
-27
No files matched your search
Generated
+6
@@ -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>
|
||||
@@ -27,6 +27,11 @@ GET http://localhost:31009/v1/spaces/{{spaceId}}/properties/{{priorityPropertyId
|
||||
Authorization: Bearer {{apiKey}}
|
||||
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 http://localhost:31009/v1/spaces/{{spaceId}}/types/{{taskTypeId}}/templates
|
||||
Authorization: Bearer {{apiKey}}
|
||||
|
||||
@@ -152,7 +152,7 @@ private fun setupSystemTray(onShow: () -> Unit, onSettings: () -> Unit, onExit:
|
||||
val icon = createTrayIcon(size)
|
||||
|
||||
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() } })
|
||||
addSeparator()
|
||||
add(MenuItem("Quit").also { it.addActionListener { onExit() } })
|
||||
|
||||
@@ -88,6 +88,15 @@ class AnyTypeApi(
|
||||
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>> =
|
||||
runCatching {
|
||||
val response = http.get("$baseUrl/v1/spaces/$spaceId/types/$typeId/templates") {
|
||||
|
||||
@@ -17,10 +17,10 @@ data class Connection(
|
||||
@Serializable
|
||||
data class PropertyConfig(
|
||||
val key: String,
|
||||
val id: String = "",
|
||||
val name: String = "",
|
||||
val format: String = "",
|
||||
val indicator: String = "",
|
||||
@SerialName("possible_values") val possibleValues: List<String> = emptyList(),
|
||||
@SerialName("object_type_key") val objectTypeKey: String = "",
|
||||
)
|
||||
|
||||
|
||||
@@ -364,7 +364,6 @@ private fun PropertyTable(
|
||||
Text("Name", fontWeight = FontWeight.Bold, modifier = Modifier.weight(2f))
|
||||
Text("Type", fontWeight = FontWeight.Bold, modifier = Modifier.weight(1.5f))
|
||||
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))
|
||||
Spacer(modifier = Modifier.width(40.dp))
|
||||
}
|
||||
@@ -383,11 +382,6 @@ private fun PropertyTable(
|
||||
Text(prop.name, modifier = Modifier.weight(2f), maxLines = 1)
|
||||
Text(prop.format, modifier = Modifier.weight(1.5f), 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)
|
||||
IconButton(onClick = { onDelete(index) }) {
|
||||
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 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 ?: "") }
|
||||
|
||||
val selectedProperty = availableProperties.find { it.key == selectedPropertyKey }
|
||||
@@ -446,15 +439,6 @@ private fun PropertyEditPanel(
|
||||
|
||||
// Format-specific fields
|
||||
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" -> {
|
||||
DropdownSelector(
|
||||
label = "Object Type",
|
||||
@@ -470,14 +454,13 @@ private fun PropertyEditPanel(
|
||||
TextButton(onClick = onCancel) { Text("Cancel") }
|
||||
Button(
|
||||
onClick = {
|
||||
val values = possibleValuesText.lines().map { it.trim() }.filter { it.isNotEmpty() }
|
||||
onConfirm(
|
||||
PropertyConfig(
|
||||
key = selectedPropertyKey,
|
||||
id = selectedProperty?.id ?: existing?.id ?: "",
|
||||
name = selectedProperty?.name ?: existing?.name ?: "",
|
||||
format = format,
|
||||
indicator = indicator,
|
||||
possibleValues = values,
|
||||
objectTypeKey = objectTypeKey,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -49,6 +49,7 @@ import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ch.ergon.anytask.api.AnyTypeApi
|
||||
import ch.ergon.anytask.api.dto.SearchObject
|
||||
import ch.ergon.anytask.api.dto.Tag
|
||||
import ch.ergon.anytask.config.Configuration
|
||||
import ch.ergon.anytask.api.dto.buildPropertyValue
|
||||
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 errorMessage by remember { mutableStateOf<String?>(null) }
|
||||
val propertyValues = remember { mutableStateMapOf<String, String>() }
|
||||
val propertyTags = remember { mutableStateMapOf<String, List<Tag>>() }
|
||||
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
@@ -144,6 +146,7 @@ fun TaskWindow(client: AnyTypeApi, config: Configuration, isVisible: Boolean, on
|
||||
value = propertyValues[prop.key] ?: "",
|
||||
onValueChange = { propertyValues[prop.key] = it },
|
||||
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
|
||||
@@ -183,13 +198,14 @@ private fun PropertyField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
client: AnyTypeApi,
|
||||
tags: List<Tag> = emptyList(),
|
||||
) {
|
||||
when (prop.format) {
|
||||
"select", "multi_select" -> {
|
||||
SelectField(
|
||||
label = prop.name,
|
||||
value = value,
|
||||
options = prop.possibleValues,
|
||||
tags = tags,
|
||||
onValueChange = onValueChange,
|
||||
)
|
||||
}
|
||||
@@ -231,16 +247,17 @@ private fun PropertyField(
|
||||
private fun SelectField(
|
||||
label: String,
|
||||
value: String,
|
||||
options: List<String>,
|
||||
tags: List<Tag>,
|
||||
onValueChange: (String) -> Unit,
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val selectedName = tags.find { it.id == value }?.name ?: value
|
||||
|
||||
Column {
|
||||
Text(label, style = MaterialTheme.typography.caption)
|
||||
Box {
|
||||
OutlinedButton(onClick = { expanded = true }, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(value.ifEmpty { "Select..." })
|
||||
Text(selectedName.ifEmpty { "Select..." })
|
||||
}
|
||||
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
|
||||
DropdownMenuItem(onClick = {
|
||||
@@ -249,12 +266,12 @@ private fun SelectField(
|
||||
}) {
|
||||
Text("(none)", style = MaterialTheme.typography.caption)
|
||||
}
|
||||
options.forEach { option ->
|
||||
tags.forEach { tag ->
|
||||
DropdownMenuItem(onClick = {
|
||||
onValueChange(option)
|
||||
onValueChange(tag.id)
|
||||
expanded = false
|
||||
}) {
|
||||
Text(option)
|
||||
Text(tag.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||