Expose backend cron self-continuity (context_from=["self"]) in the Cron editor. Adds a Run Continuity checkbox to the job editor that sends context_from=["self"] on create and update (null when off, clearing it), prefills from the loaded job's context_from, and shows a "Continuity" badge on recurring jobs in the list. context_from was already on CronJob and CreateCronJobRequest, so this is editor/list wiring only. Strings added for en/zh/ko. Includes two ViewModel tests. Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
50a0f30d8f
commit
1039d7db1d
6 files changed
+122
No files matched your search
@@ -186,6 +186,14 @@ fun CronJobsScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
// Run-continuity badge: the job's own previous
|
||||
// output is injected into each run.
|
||||
if (job.context_from?.contains("self") == true) {
|
||||
StatusBadge(
|
||||
text = stringResource(R.string.cron_badge_continuity),
|
||||
status = StatusBadgeType.INFO,
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(spacing.xs))
|
||||
Text(
|
||||
@@ -267,6 +275,7 @@ fun CronJobsScreen(
|
||||
state = state.editorState,
|
||||
onFieldChange = { name, value -> viewModel.updateEditorField(name, value) },
|
||||
onToggleNoAgent = { viewModel.toggleNoAgent() },
|
||||
onToggleRunContinuity = { viewModel.toggleRunContinuity() },
|
||||
onSetMonitorMode = { viewModel.setMonitorMode(it) },
|
||||
onSelectBlueprint = { viewModel.selectBlueprint(it) },
|
||||
onBlueprintFieldChange = { name, value -> viewModel.updateBlueprintValue(name, value) },
|
||||
@@ -331,6 +340,7 @@ fun CronJobEditorDialog(
|
||||
state: CronJobEditorState,
|
||||
onFieldChange: (String, String) -> Unit,
|
||||
onToggleNoAgent: () -> Unit,
|
||||
onToggleRunContinuity: () -> Unit,
|
||||
onSetMonitorMode: (String) -> Unit,
|
||||
onSelectBlueprint: (String?) -> Unit,
|
||||
onBlueprintFieldChange: (String, String) -> Unit,
|
||||
@@ -571,6 +581,30 @@ fun CronJobEditorDialog(
|
||||
)
|
||||
}
|
||||
|
||||
// Run Continuity toggle (recurring jobs: inject own
|
||||
// previous output into each run via context_from=["self"])
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Checkbox(
|
||||
checked = state.runContinuity,
|
||||
onCheckedChange = { onToggleRunContinuity() },
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = stringResource(R.string.cron_edit_field_run_continuity),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.cron_edit_hint_run_continuity),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Monitor mode (disabled for no-agent jobs — the
|
||||
// backend rejects monitor + no_agent together)
|
||||
MonitorModeSection(
|
||||
|
||||
@@ -58,6 +58,10 @@ data class CronJobEditorState(
|
||||
val workdir: String = "",
|
||||
val enabled: Boolean = true,
|
||||
val no_agent: Boolean = false,
|
||||
// Run continuity: when true, the job's own previous output is injected
|
||||
// into each subsequent run via context_from=["self"] (backend cron
|
||||
// self-continuity). Only meaningful for recurring jobs.
|
||||
val runContinuity: Boolean = false,
|
||||
// Monitor mode: one of monitor_script / monitor_url set at a time
|
||||
// (mutually exclusive on the backend; incompatible with no_agent).
|
||||
val monitorMode: String = "off", // "off" | "script" | "url"
|
||||
@@ -309,6 +313,7 @@ class CronJobsViewModel :
|
||||
workdir = job.workdir.orEmpty(),
|
||||
enabled = job.enabled ?: true,
|
||||
no_agent = job.no_agent ?: false,
|
||||
runContinuity = job.context_from?.contains("self") ?: false,
|
||||
monitorMode =
|
||||
when {
|
||||
!job.monitor_script.isNullOrBlank() -> "script"
|
||||
@@ -425,6 +430,8 @@ class CronJobsViewModel :
|
||||
updates["script"] = editor.script.ifBlank { null }
|
||||
updates["workdir"] = editor.workdir.ifBlank { null }
|
||||
updates["no_agent"] = editor.no_agent
|
||||
// Run continuity: send ["self"] when on, null (clears) when off.
|
||||
updates["context_from"] = if (editor.runContinuity) listOf("self") else null
|
||||
// Blank clears the monitor source on the backend (empty
|
||||
// string or null both mean "clear the field").
|
||||
updates["monitor_script"] = editor.monitor_script.ifBlank { null }
|
||||
@@ -488,6 +495,7 @@ class CronJobsViewModel :
|
||||
script = editor.script.ifBlank { null },
|
||||
workdir = editor.workdir.ifBlank { null },
|
||||
no_agent = editor.no_agent,
|
||||
context_from = if (editor.runContinuity) listOf("self") else null,
|
||||
monitor_script = editor.monitor_script.ifBlank { null },
|
||||
monitor_url = editor.monitor_url.ifBlank { null },
|
||||
),
|
||||
@@ -553,12 +561,25 @@ class CronJobsViewModel :
|
||||
"base_url" -> copy(base_url = value)
|
||||
"script" -> copy(script = value)
|
||||
"workdir" -> copy(workdir = value)
|
||||
"run_continuity" -> copy(runContinuity = value.toBooleanStrictOrNull() ?: false)
|
||||
// Monitor fields are mutually exclusive: entering one clears the other.
|
||||
"monitor_script" -> copy(monitor_script = value, monitor_url = if (value.isNotBlank()) "" else monitor_url)
|
||||
"monitor_url" -> copy(monitor_url = value, monitor_script = if (value.isNotBlank()) "" else monitor_script)
|
||||
else -> this
|
||||
}
|
||||
|
||||
fun toggleRunContinuity() {
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
editorState =
|
||||
it.editorState.copy(
|
||||
runContinuity = !it.editorState.runContinuity,
|
||||
toastMessage = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleNoAgent() {
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
|
||||
Reference in new issue
Block a user