feat(cron): require job name
This commit is contained in:
@@ -145,7 +145,8 @@ struct CronJobState: Codable, Equatable {
|
||||
|
||||
struct CronJob: Identifiable, Codable, Equatable {
|
||||
let id: String
|
||||
var name: String?
|
||||
var name: String
|
||||
var description: String?
|
||||
var enabled: Bool
|
||||
let createdAtMs: Int
|
||||
let updatedAtMs: Int
|
||||
@@ -157,7 +158,7 @@ struct CronJob: Identifiable, Codable, Equatable {
|
||||
let state: CronJobState
|
||||
|
||||
var displayName: String {
|
||||
let trimmed = (self.name ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let trimmed = self.name.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return trimmed.isEmpty ? "Untitled job" : trimmed
|
||||
}
|
||||
|
||||
|
||||
@@ -277,6 +277,9 @@ struct CronSettings: View {
|
||||
private func detailCard(_ job: CronJob) -> some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
LabeledContent("Schedule") { Text(self.scheduleSummary(job.schedule)).font(.callout) }
|
||||
if let desc = job.description, !desc.isEmpty {
|
||||
LabeledContent("Description") { Text(desc).font(.callout) }
|
||||
}
|
||||
LabeledContent("Session") { Text(job.sessionTarget.rawValue) }
|
||||
LabeledContent("Wake") { Text(job.wakeMode.rawValue) }
|
||||
LabeledContent("Next run") {
|
||||
@@ -514,6 +517,7 @@ struct CronJobEditor: View {
|
||||
"Controls the label used when posting the completion summary back to the main session."
|
||||
|
||||
@State private var name: String = ""
|
||||
@State private var description: String = ""
|
||||
@State private var enabled: Bool = true
|
||||
@State private var sessionTarget: CronSessionTarget = .main
|
||||
@State private var wakeMode: CronWakeMode = .nextHeartbeat
|
||||
@@ -554,7 +558,13 @@ struct CronJobEditor: View {
|
||||
Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) {
|
||||
GridRow {
|
||||
self.gridLabel("Name")
|
||||
TextField("Optional label (e.g. “Daily summary”)", text: self.$name)
|
||||
TextField("Required (e.g. “Daily summary”)", text: self.$name)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
GridRow {
|
||||
self.gridLabel("Description")
|
||||
TextField("Optional notes", text: self.$description)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
@@ -833,7 +843,8 @@ struct CronJobEditor: View {
|
||||
|
||||
private func hydrateFromJob() {
|
||||
guard let job else { return }
|
||||
self.name = job.name ?? ""
|
||||
self.name = job.name
|
||||
self.description = job.description ?? ""
|
||||
self.enabled = job.enabled
|
||||
self.sessionTarget = job.sessionTarget
|
||||
self.wakeMode = job.wakeMode
|
||||
@@ -881,6 +892,13 @@ struct CronJobEditor: View {
|
||||
|
||||
private func buildPayload() throws -> [String: AnyCodable] {
|
||||
let name = self.name.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if name.isEmpty {
|
||||
throw NSError(
|
||||
domain: "Cron",
|
||||
code: 0,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Name is required."])
|
||||
}
|
||||
let description = self.description.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let schedule: [String: Any]
|
||||
switch self.scheduleKind {
|
||||
case .at:
|
||||
@@ -954,13 +972,14 @@ struct CronJobEditor: View {
|
||||
}
|
||||
|
||||
var root: [String: Any] = [
|
||||
"name": name,
|
||||
"enabled": self.enabled,
|
||||
"schedule": schedule,
|
||||
"sessionTarget": self.sessionTarget.rawValue,
|
||||
"wakeMode": self.wakeMode.rawValue,
|
||||
"payload": payload,
|
||||
]
|
||||
if !name.isEmpty { root["name"] = name }
|
||||
if !description.isEmpty { root["description"] = description }
|
||||
|
||||
if self.sessionTarget == .isolated {
|
||||
let trimmed = self.postPrefix.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
@@ -1035,6 +1054,7 @@ struct CronSettings_Previews: PreviewProvider {
|
||||
CronJob(
|
||||
id: "job-1",
|
||||
name: "Daily summary",
|
||||
description: nil,
|
||||
enabled: true,
|
||||
createdAtMs: 0,
|
||||
updatedAtMs: 0,
|
||||
|
||||
@@ -672,7 +672,8 @@ public struct SkillsUpdateParams: Codable {
|
||||
|
||||
public struct CronJob: Codable {
|
||||
public let id: String
|
||||
public let name: String?
|
||||
public let name: String
|
||||
public let description: String?
|
||||
public let enabled: Bool
|
||||
public let createdatms: Int
|
||||
public let updatedatms: Int
|
||||
@@ -685,7 +686,8 @@ public struct CronJob: Codable {
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
name: String?,
|
||||
name: String,
|
||||
description: String?,
|
||||
enabled: Bool,
|
||||
createdatms: Int,
|
||||
updatedatms: Int,
|
||||
@@ -698,6 +700,7 @@ public struct CronJob: Codable {
|
||||
) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.enabled = enabled
|
||||
self.createdatms = createdatms
|
||||
self.updatedatms = updatedatms
|
||||
@@ -711,6 +714,7 @@ public struct CronJob: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case name
|
||||
case description
|
||||
case enabled
|
||||
case createdatms = "createdAtMs"
|
||||
case updatedatms = "updatedAtMs"
|
||||
@@ -740,7 +744,8 @@ public struct CronStatusParams: Codable {
|
||||
}
|
||||
|
||||
public struct CronAddParams: Codable {
|
||||
public let name: String?
|
||||
public let name: String
|
||||
public let description: String?
|
||||
public let enabled: Bool?
|
||||
public let schedule: AnyCodable
|
||||
public let sessiontarget: AnyCodable
|
||||
@@ -749,7 +754,8 @@ public struct CronAddParams: Codable {
|
||||
public let isolation: [String: AnyCodable]?
|
||||
|
||||
public init(
|
||||
name: String?,
|
||||
name: String,
|
||||
description: String?,
|
||||
enabled: Bool?,
|
||||
schedule: AnyCodable,
|
||||
sessiontarget: AnyCodable,
|
||||
@@ -758,6 +764,7 @@ public struct CronAddParams: Codable {
|
||||
isolation: [String: AnyCodable]?
|
||||
) {
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.enabled = enabled
|
||||
self.schedule = schedule
|
||||
self.sessiontarget = sessiontarget
|
||||
@@ -767,6 +774,7 @@ public struct CronAddParams: Codable {
|
||||
}
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name
|
||||
case description
|
||||
case enabled
|
||||
case schedule
|
||||
case sessiontarget = "sessionTarget"
|
||||
|
||||
@@ -61,6 +61,7 @@ struct CronModelsTests {
|
||||
let base = CronJob(
|
||||
id: "x",
|
||||
name: " hello ",
|
||||
description: nil,
|
||||
enabled: true,
|
||||
createdAtMs: 0,
|
||||
updatedAtMs: 0,
|
||||
@@ -81,6 +82,7 @@ struct CronModelsTests {
|
||||
let job = CronJob(
|
||||
id: "x",
|
||||
name: "t",
|
||||
description: nil,
|
||||
enabled: true,
|
||||
createdAtMs: 0,
|
||||
updatedAtMs: 0,
|
||||
|
||||
Reference in New Issue
Block a user