using ClawdDotNet.Core.Config; using ClawdDotNet.Core.Scheduling; using ClawdDotNet.Core.Tools; namespace ClawdDotNet; public sealed partial class frm_AddJob : Form { private readonly IReadOnlyList _agents; private readonly IReadOnlyList<(IAgentTool Tool, IToolJobProvider Provider)> _jobProviders; // ─── Output Properties ─── public bool IsToolJob => cbJobType.SelectedIndex == 1; public string SelectedAgentId => (cbAgent.SelectedItem as AgentComboItem)?.AgentId ?? ""; public string CronExpression => txtCron.Text.Trim(); public string TaskMessage => txtTask.Text.Trim(); public bool RunOnStart => chkRunOnStart.Checked; public string SelectedToolName => (cbTool.SelectedItem as ToolComboItem)?.ToolName ?? ""; public string SelectedJobTypeId => (cbJobDef.SelectedItem as JobDefComboItem)?.JobTypeId ?? ""; /// Konstruktor für "Hinzufügen" public frm_AddJob(IReadOnlyList agents, ToolRegistry toolRegistry) { InitializeComponent(); _agents = agents; _jobProviders = toolRegistry.GetJobProviders(); foreach (var agent in agents) cbAgent.Items.Add(new AgentComboItem(agent.AgentId, agent.DisplayName)); if (cbAgent.Items.Count > 0) cbAgent.SelectedIndex = 0; foreach (var (tool, _) in _jobProviders) cbTool.Items.Add(new ToolComboItem(tool.Name, tool.Description)); if (cbTool.Items.Count > 0) cbTool.SelectedIndex = 0; cbJobType.SelectedIndex = 0; } /// Konstruktor für "Bearbeiten" — Agent, Tool und Job-Typ sind gesperrt public frm_AddJob(IReadOnlyList agents, ToolRegistry toolRegistry, string agentId, string cron, string taskMessage, bool runOnStart, bool isToolJob, string? toolName = null, string? jobTypeId = null) : this(agents, toolRegistry) { Text = "Job bearbeiten"; btnOk.Text = "Speichern"; // Job-Typ setzen und sperren cbJobType.SelectedIndex = isToolJob ? 1 : 0; cbJobType.Enabled = false; // Agent vorauswählen und sperren for (int i = 0; i < cbAgent.Items.Count; i++) { if (((AgentComboItem)cbAgent.Items[i]!).AgentId == agentId) { cbAgent.SelectedIndex = i; break; } } cbAgent.Enabled = false; // Bearbeitbare Felder befüllen txtCron.Text = cron; chkRunOnStart.Checked = runOnStart; if (isToolJob && toolName is not null) { // Tool vorauswählen und sperren for (int i = 0; i < cbTool.Items.Count; i++) { if (((ToolComboItem)cbTool.Items[i]!).ToolName == toolName) { cbTool.SelectedIndex = i; break; } } cbTool.Enabled = false; // Job-Definition vorauswählen und sperren if (jobTypeId is not null) { for (int i = 0; i < cbJobDef.Items.Count; i++) { if (((JobDefComboItem)cbJobDef.Items[i]!).JobTypeId == jobTypeId) { cbJobDef.SelectedIndex = i; break; } } } cbJobDef.Enabled = false; } else { txtTask.Text = taskMessage; } } private void OnJobTypeChanged(object? sender, EventArgs e) { var isToolJob = cbJobType.SelectedIndex == 1; lblTool.Visible = isToolJob; cbTool.Visible = isToolJob; lblJobDef.Visible = isToolJob; cbJobDef.Visible = isToolJob; lblTask.Visible = !isToolJob; txtTask.Visible = !isToolJob; RefreshAgentList(); } private void OnToolChanged(object? sender, EventArgs e) { cbJobDef.Items.Clear(); if (cbTool.SelectedItem is not ToolComboItem toolItem) return; var provider = _jobProviders.FirstOrDefault(p => ((IAgentTool)p.Provider).Name == toolItem.ToolName); if (provider.Provider is null) return; foreach (var def in provider.Provider.GetJobDefinitions()) cbJobDef.Items.Add(new JobDefComboItem(def.JobTypeId, def.DisplayName, def.Description)); if (cbJobDef.Items.Count > 0) cbJobDef.SelectedIndex = 0; RefreshAgentList(); } private void RefreshAgentList() { var previousAgentId = (cbAgent.SelectedItem as AgentComboItem)?.AgentId; cbAgent.Items.Clear(); var toolName = IsToolJob && cbTool.SelectedItem is ToolComboItem toolItem ? toolItem.ToolName : null; foreach (var agent in _agents) { if (toolName is not null && !agent.Tools.ContainsKey(toolName)) continue; cbAgent.Items.Add(new AgentComboItem(agent.AgentId, agent.DisplayName)); } if (previousAgentId is not null) { for (int i = 0; i < cbAgent.Items.Count; i++) { if (((AgentComboItem)cbAgent.Items[i]!).AgentId == previousAgentId) { cbAgent.SelectedIndex = i; break; } } } if (cbAgent.SelectedIndex < 0 && cbAgent.Items.Count > 0) cbAgent.SelectedIndex = 0; } private void OnCronChanged(object? sender, EventArgs e) { var text = txtCron.Text.Trim(); if (string.IsNullOrWhiteSpace(text)) { lblPreview.Text = ""; return; } try { var cron = Core.Scheduling.CronExpression.Parse(text); var next = cron.GetNextOccurrence(DateTime.Now); lblPreview.Text = next is not null ? $"Nächste Ausführung: {next:dd.MM.yyyy HH:mm}" : "Kein nächster Zeitpunkt"; lblPreview.ForeColor = Color.Green; } catch { lblPreview.Text = "Ungültiger Cron-Ausdruck"; lblPreview.ForeColor = Color.Red; } } private void OnOkClick(object? sender, EventArgs e) { if (cbAgent.SelectedItem is null) { MessageBox.Show("Bitte einen Agenten auswählen.", "Validierung", MessageBoxButtons.OK, MessageBoxIcon.Warning); DialogResult = DialogResult.None; return; } if (string.IsNullOrWhiteSpace(txtCron.Text)) { MessageBox.Show("Bitte einen Cron-Ausdruck eingeben.", "Validierung", MessageBoxButtons.OK, MessageBoxIcon.Warning); DialogResult = DialogResult.None; return; } try { Core.Scheduling.CronExpression.Parse(txtCron.Text.Trim()); } catch { MessageBox.Show("Ungültiger Cron-Ausdruck.", "Validierung", MessageBoxButtons.OK, MessageBoxIcon.Warning); DialogResult = DialogResult.None; return; } if (IsToolJob) { if (cbTool.SelectedItem is null) { MessageBox.Show("Bitte ein Tool auswählen.", "Validierung", MessageBoxButtons.OK, MessageBoxIcon.Warning); DialogResult = DialogResult.None; return; } if (cbJobDef.SelectedItem is null) { MessageBox.Show("Bitte einen Job-Typ auswählen.", "Validierung", MessageBoxButtons.OK, MessageBoxIcon.Warning); DialogResult = DialogResult.None; } } } // ─── ComboBox Items ─── private sealed record AgentComboItem(string AgentId, string DisplayName) { public override string ToString() => DisplayName; } private sealed record ToolComboItem(string ToolName, string Description) { public override string ToString() => ToolName; } private sealed record JobDefComboItem(string JobTypeId, string DisplayName, string Description) { public override string ToString() => $"{DisplayName} ({JobTypeId})"; } }