1use super::types::Message;
30use std::fmt::{Display, Formatter, Result};
31
32impl Display for Message {
33 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
103 let text = match self {
104 Message::AutostartEnabled => "Autostart has been enabled. Kasl will start automatically on system boot.".to_string(),
106 Message::AutostartEnabledUser => "Autostart has been enabled for current user. Kasl will start when you log in.".to_string(),
107 Message::AutostartDisabled => "Autostart has been disabled.".to_string(),
108 Message::AutostartAlreadyDisabled => "Autostart was already disabled.".to_string(),
109 Message::AutostartEnableFailed(error) => format!("Failed to enable autostart: {}", error),
110 Message::AutostartDisableFailed(error) => format!("Failed to disable autostart: {}", error),
111 Message::AutostartStatus(status) => format!("Autostart is currently: {}", status),
112 Message::AutostartNotImplemented => "Autostart is not yet implemented for this operating system.".to_string(),
113 Message::AutostartRequiresAdmin => "Administrator privileges required for system-level autostart. Trying user-level alternative...".to_string(),
114 Message::AutostartCheckingAlternative => "Checking alternative autostart method...".to_string(),
115
116 Message::TaskCreated => "Task created successfully".to_string(),
118 Message::TaskUpdated => "Task updated successfully".to_string(),
119 Message::TaskDeleted => "Task deleted successfully".to_string(),
120 Message::TaskNotFound => "Task not found".to_string(),
121 Message::TaskCreateFailed => "Failed to create task".to_string(),
122 Message::TaskUpdateFailed => "Failed to update task".to_string(),
123 Message::TaskDeleteFailed => "Failed to delete task".to_string(),
124 Message::TasksDeletedCount(count) => format!("Deleted {} task(s) successfully.", count),
125 Message::TasksNotFoundForDate(date) => format!("Tasks not found for {}, report not sent.", date),
126 Message::TasksNotFoundSad => "No tasks found.".to_string(),
127 Message::TasksHeader => "Tasks:".to_string(),
128 Message::TasksIncompleteHeader => "Incomplete tasks".to_string(),
129 Message::TasksGitlabHeader => "Gitlab commits".to_string(),
130 Message::TasksJiraHeader => "Jira issues".to_string(),
131 Message::TasksDiscoverySummary { incomplete, jira, gitlab } => {
132 let mut parts = Vec::new();
133 if *incomplete > 0 {
134 parts.push(format!("{} incomplete", incomplete));
135 }
136 if *jira > 0 {
137 parts.push(format!("{} jira", jira));
138 }
139 if *gitlab > 0 {
140 parts.push(format!("{} gitlab", gitlab));
141 }
142 format!("Found: {}", parts.join(", "))
143 }
144 Message::TasksDiscoverySeparator => "──────── other ────────".to_string(),
145 Message::TasksDiscoverySearchingIncomplete => "Looking for incomplete tasks...".to_string(),
146 Message::TasksDiscoveryFetchingExternal => "Fetching GitLab commits and Jira issues...".to_string(),
147 Message::NoTaskIdsProvided => "No task IDs provided for deletion.".to_string(),
148 Message::TasksNotFoundForIds(ids) => format!("No tasks found with IDs: {:?}", ids),
149 Message::TasksToBeDeleted => "The following tasks will be deleted:".to_string(),
150 Message::ConfirmDeleteTask => "Are you sure you want to delete this task?".to_string(),
151 Message::ConfirmDeleteTasks(count) => format!("Are you sure you want to delete {} tasks?", count),
152 Message::ConfirmDeleteAllTodayTasks(count) => format!("Are you sure you want to delete ALL {} tasks for today?", count),
153 Message::ConfirmDeleteAllTodayTasksFinal => "This action cannot be undone. Are you REALLY sure?".to_string(),
154 Message::NoTasksForToday => "No tasks found for today.".to_string(),
155 Message::TaskNotFoundWithId(id) => format!("Task with ID {} not found.", id),
156 Message::CurrentTaskState => "Current task:".to_string(),
157 Message::TaskEditPreview => "Task after changes:".to_string(),
158 Message::ConfirmTaskUpdate => "Save changes?".to_string(),
159 Message::NoChangesDetected => "No changes detected.".to_string(),
160 Message::NoTasksSelected => "No tasks selected for editing.".to_string(),
161 Message::SelectTasksToEdit => "Select tasks to edit (space to select, enter to confirm)".to_string(),
162 Message::EditingTask(name) => format!("Editing task: {}", name),
163 Message::TaskUpdatedWithName(name) => format!("Task '{}' updated successfully.", name),
164 Message::TaskSkippedNoChanges(name) => format!("Task '{}' - no changes, skipped.", name),
165 Message::TaskEditingCompleted => "Task editing completed.".to_string(),
166 Message::PromptTaskNameEdit => "Task name".to_string(),
167 Message::PromptTaskCommentEdit => "Comment (optional)".to_string(),
168 Message::PromptTaskCompletenessEdit => "Completeness (0-100)".to_string(),
169 Message::TaskCompletenessRange => "Completeness must be between 0 and 100".to_string(),
170
171 Message::WorkdayEnded => "Workday ended for today.".to_string(),
173 Message::WorkdayNotFound => "No workday record found".to_string(),
174 Message::WorkdayNotFoundForDate(date) => format!("No workday record found for {}", date),
175 Message::WorkdayCreateFailed => "Failed to create workday".to_string(),
176 Message::WorkdayStarting(date) => format!("Starting workday for {}", date),
177 Message::WorkdayCouldNotFindAfterFinalizing(date) => {
178 format!("Could not find workday for {} after finalizing.", date)
179 }
180
181 Message::ConfigSaved => "Configuration saved successfully".to_string(),
183 Message::ConfigDeleted => "Configuration deleted successfully".to_string(),
184 Message::ConfigLoaded => "Configuration loaded successfully".to_string(),
185 Message::ConfigFileNotFound => "Configuration file not found".to_string(),
186 Message::ConfigParseError => "Failed to parse configuration".to_string(),
187 Message::ConfigSaveError => "Failed to save configuration".to_string(),
188 Message::ConfigModuleGitLab => "GitLab settings".to_string(),
189 Message::ConfigModuleJira => "Jira settings".to_string(),
190 Message::ConfigModuleSiServer => "SiServer settings".to_string(),
191 Message::ConfigModuleMonitor => "Monitor settings".to_string(),
192 Message::ConfigModuleServer => "Server settings".to_string(),
193 Message::ConfigModuleProductivity => "Productivity settings".to_string(),
194 Message::ConfigModuleTaskDiscovery => "Task discovery settings".to_string(),
195 Message::ConfigModuleJiraInbox => "Jira inbox settings".to_string(),
196 Message::TaskDiscoveryIgnoreListHeader => "Current ignore list:".to_string(),
197 Message::TaskDiscoveryIgnoreListEmpty => "Ignore list is empty.".to_string(),
198 Message::TaskDiscoveryIgnoreNameAdded(name) => format!("Added '{}' to ignore list.", name),
199 Message::TaskDiscoveryIgnoreNameExists(name) => format!("'{}' is already in the ignore list.", name),
200 Message::TaskDiscoveryIgnoreNamesAdded(count) => {
201 format!("Added {} name(s) to the discovery ignore list.", count)
202 }
203
204 Message::DailyReportSent(date) => {
206 format!(
207 "Your report dated {} has been successfully submitted\nWait for a message to your email address",
208 date
209 )
210 }
211 Message::MonthlyReportSent(date) => {
212 format!(
213 "Your monthly report dated {} has been successfully submitted\nWait for a message to your email address",
214 date
215 )
216 }
217 Message::MonthlyReportTriggered => "It's the last working day of the month. Submitting the monthly report as well...".to_string(),
218 Message::ReportSendFailed(status) => format!("Failed to send report. Status: {}", status),
219 Message::MonthlyReportSendFailed(status) => format!("Failed to send monthly report. Status: {}", status),
220 Message::ReportHeader(date) => format!("Report for {}", date),
221 Message::WorkingHoursForMonth(month_year) => format!("Working hours for {}", month_year),
222
223 Message::ExportingData(data, format) => format!("Exporting {} in {} format...", data, format),
225 Message::ExportCompleted(path) => format!("Export completed successfully: {}", path),
226 Message::ExportingAllData => "Exporting all data...".to_string(),
227 Message::ExportFailed(error) => format!("Export failed: {}", error),
228
229 Message::TemplateCreated(name) => format!("Template '{}' created successfully.", name),
231 Message::TemplateUpdated(name) => format!("Template '{}' updated successfully.", name),
232 Message::TemplateDeleted(name) => format!("Template '{}' deleted successfully.", name),
233 Message::TemplateNotFound(name) => format!("Template '{}' not found.", name),
234 Message::TemplateAlreadyExists(name) => format!("Template '{}' already exists.", name),
235 Message::TemplateCreateFailed => "Failed to create template.".to_string(),
236 Message::NoTemplatesFound => "No templates found.".to_string(),
237 Message::TemplateListHeader => "Task Templates:".to_string(),
238 Message::SelectTemplateToEdit => "Select template to edit".to_string(),
239 Message::SelectTemplateToDelete => "Select template to delete".to_string(),
240 Message::ConfirmDeleteTemplate(name) => format!("Delete template '{}'?", name),
241 Message::EditingTemplate(name) => format!("Editing template: {}", name),
242 Message::NoTemplatesMatchingQuery(query) => format!("No templates matching '{}'", query),
243 Message::TemplateSearchResults(query) => format!("Templates matching '{}':", query),
244 Message::SelectTemplateAction => "What would you like to do?".to_string(),
245 Message::PromptTemplateName => "Template name (unique identifier)".to_string(),
246 Message::PromptTemplateTaskName => "Task name".to_string(),
247 Message::PromptTemplateComment => "Comment (optional)".to_string(),
248 Message::PromptTemplateCompleteness => "Default completeness (0-100)".to_string(),
249 Message::CreatingTaskFromTemplate(name) => format!("Creating task from template '{}'", name),
250 Message::SelectTemplate => "Select a template".to_string(),
251 Message::CreateTemplateFirst => "Create templates with 'kasl template add'".to_string(),
252
253 Message::TagCreated(name) => format!("Tag '{}' created successfully.", name),
255 Message::TagUpdated(name) => format!("Tag '{}' updated successfully.", name),
256 Message::TagDeleted(name) => format!("Tag '{}' deleted successfully.", name),
257 Message::TagNotFound(name) => format!("Tag '{}' not found.", name),
258 Message::TagAlreadyExists(name) => format!("Tag '{}' already exists.", name),
259 Message::NoTagsFound => "No tags found.".to_string(),
260 Message::TagListHeader => "Tags:".to_string(),
261 Message::EditingTag(name) => format!("Editing tag: {}", name),
262 Message::SelectTagAction => "What would you like to do?".to_string(),
263 Message::SelectTagToEdit => "Select tag to edit".to_string(),
264 Message::SelectTagToDelete => "Select tag to delete".to_string(),
265 Message::ConfirmDeleteTag(name) => format!("Delete tag '{}'?", name),
266 Message::ConfirmDeleteTagWithTasks(name, count) => format!("Tag '{}' is used by {} task(s). Delete anyway?", name, count),
267 Message::PromptTagName => "Tag name".to_string(),
268 Message::PromptTagColor => "Tag color (e.g., blue, green, red)".to_string(),
269 Message::NoTasksWithTag(tag) => format!("No tasks found with tag '{}'.", tag),
270 Message::TasksWithTag(tag) => format!("Tasks with tag '{}':", tag),
271 Message::TagsAddedToTask(tags) => format!("Tags added: {}", tags),
272
273 Message::ShortIntervalsDetected(count, duration) => format!("Found {} short work intervals (total: {})", count, duration),
275 Message::NoShortIntervalsFound(min) => format!("No work intervals shorter than {} minutes found.", min),
276 Message::ShortIntervalsToRemove(count) => format!("Found {} short intervals to remove:", count),
277 Message::RemovingPauses(count) => format!("Removing {} pauses to merge intervals...", count),
278 Message::ShortIntervalsCleared(count) => format!("Successfully removed {} pauses and merged intervals.", count),
279 Message::NoRemovablePausesFound => "No pauses found that can be removed to clear short intervals.".to_string(),
280 Message::UpdatedReport => "Updated report:".to_string(),
281 Message::PromptMinWorkInterval => "Minimum work interval (minutes)".to_string(),
282
283 Message::SelectAdjustmentMode => "Select adjustment mode".to_string(),
285 Message::PromptAdjustmentMinutes => "How many minutes to adjust?".to_string(),
286 Message::PromptPauseStartTime => "When should the pause start? (HH:MM)".to_string(),
287 Message::ConfirmTimeAdjustment => "Apply this time adjustment?".to_string(),
288 Message::TimeAdjustmentApplied => "Time adjustment applied successfully.".to_string(),
289 Message::AdjustmentPreview => "Time adjustment preview:".to_string(),
290 Message::InvalidAdjustmentTooMuchTime => "Cannot adjust that much time - would result in invalid workday.".to_string(),
291 Message::InvalidPauseOutsideWorkday => "Pause must be within workday hours.".to_string(),
292 Message::WorkdayUpdateFailed => "Failed to update workday.".to_string(),
293
294 Message::PausesTitle(date) => format!("Pauses for {}", date),
296
297 Message::MonitorStarted {
299 pause_threshold,
300 poll_interval,
301 activity_threshold,
302 } => {
303 format!(
304 "Monitor is running with pause threshold {}s, poll interval {}ms, activity threshold {}s",
305 pause_threshold, poll_interval, activity_threshold
306 )
307 }
308 Message::MonitorStopped => "Monitor stopped".to_string(),
309 Message::MonitorStartFailed => "Failed to start monitor".to_string(),
310 Message::MonitorStopFailed => "Failed to stop monitor".to_string(),
311 Message::MonitorExitedNormally => "Monitor exited normally".to_string(),
312 Message::MonitorShuttingDown => "Shutting down monitor...".to_string(),
313 Message::MonitorError(error) => format!("Monitor error: {}", error),
314 Message::MonitorTaskPanicked(error) => format!("Monitor task panicked: {}", error),
315 Message::PauseStarted => "Pause Start".to_string(),
316 Message::PauseEnded => "Pause End".to_string(),
317
318 Message::WatcherStarted(pid) => format!("Watcher started in the background (PID: {}).", pid),
320 Message::WatcherStopped(pid) => format!("Watcher process (PID: {}) stopped successfully.", pid),
321 Message::WatcherStoppedSuccessfully => "Watcher stopped successfully".to_string(),
322 Message::WatcherNotRunning => "Watcher is not running.".to_string(),
323 Message::WatcherNotRunningPidNotFound => "Watcher does not appear to be running (PID file not found).".to_string(),
324 Message::WatcherStartingForeground => "Starting watcher in foreground... Press Ctrl+C to exit.".to_string(),
325 Message::WatcherStoppingExisting(pid) => format!("Stopping existing watcher (PID: {})...", pid),
326 Message::WatcherFailedToStopExisting(error) => format!("Warning: Failed to stop existing daemon: {}", error),
327 Message::WatcherFailedToStop(pid) => format!("Failed to stop watcher process (PID: {})", pid),
328 Message::WatcherReceivedSigterm => "Received SIGTERM, shutting down gracefully...".to_string(),
329 Message::WatcherReceivedSigint => "Received SIGINT, shutting down gracefully...".to_string(),
330 Message::WatcherReceivedCtrlC => "Received Ctrl+C, shutting down gracefully...".to_string(),
331 Message::WatcherCtrlCListenFailed(error) => format!("Failed to listen for Ctrl+C: {}", error),
332 Message::WatcherSignalHandlingNotSupported => "Warning: Signal handling not supported on this platform".to_string(),
333 Message::DaemonModeNotSupported => "Daemon mode is not supported on this platform.".to_string(),
334 Message::FailedToGetCurrentExecutable => "Failed to get the path of the current executable".to_string(),
335 Message::FailedToCreateSigtermHandler => "Failed to create SIGTERM handler".to_string(),
336 Message::FailedToCreateSigintHandler => "Failed to create SIGINT handler".to_string(),
337
338 Message::UpdateAvailable { app_name, latest } => {
340 format!(
341 "A new version of {} is available: v{}\nUpgrade now by running: {} update",
342 app_name, latest, app_name
343 )
344 }
345 Message::UpdateCompleted { app_name, version } => {
346 format!("The {} application has been successfully updated to version {}!", app_name, version)
347 }
348 Message::NoUpdateRequired => "No update required. You are using the latest version!".to_string(),
349 Message::UpdateDownloadUrlNotSet => "Download URL not set".to_string(),
350 Message::WatcherStoppingForUpdate => "Stopping watcher for update...".to_string(),
351 Message::WatcherRestartingAfterUpdate => "Restarting watcher after update...".to_string(),
352 Message::WatcherStoppingForConfig => "Stopping watcher to apply new configuration...".to_string(),
353 Message::WatcherRestartingAfterConfig => "Restarting watcher with updated configuration...".to_string(),
354 Message::WatcherRestarted => "Watcher successfully restarted with new configuration".to_string(),
355 Message::WatcherRestartFailed { error } => format!("Warning: Failed to restart watcher: {}", error),
356 Message::UpdateBinaryNotFoundInArchive => "Binary not found in the release archive.".to_string(),
357
358 Message::WrongPassword(count) => format!("You entered the wrong password {} times!", count),
360 Message::InvalidCredentials => "Invalid credentials".to_string(),
361 Message::SessionExpired => "Session expired".to_string(),
362 Message::AuthenticationFailed(service) => format!("Authentication failed: {}", service),
363 Message::JiraAuthenticateFailed => "Jira authenticate failed".to_string(),
364 Message::LoginFailed => "Login failed".to_string(),
365 Message::CredentialsNotSet => "Credentials not set!".to_string(),
366
367 Message::ApiConnectionFailed => "Failed to connect to API".to_string(),
369 Message::ApiAuthFailed => "API authentication failed".to_string(),
370 Message::ApiRequestFailed => "API request failed".to_string(),
371 Message::GitlabFetchFailed(error) => format!("[kasl] Failed to get GitLab events: {}", error),
372 Message::GitlabUserIdFailed(error) => format!("[kasl] Failed to get GitLab user ID: {}", error),
373 Message::JiraFetchFailed(error) => format!("[kasl] Failed to get Jira issues: {}", error),
374 Message::SiServerConfigNotFound => "SiServer configuration not found in config file.".to_string(),
375 Message::SiServerSessionFailed(error) => format!("[kasl] Failed to get SiServer session for rest dates: {}", error),
376 Message::SiServerRestDatesFailed(error) => format!("[kasl] Failed to request rest dates: {}", error),
377 Message::SiServerRestDatesParsingFailed(error) => format!("[kasl] Failed to parse rest dates response: {}", error),
378
379 Message::DbConnectionFailed => "Failed to connect to database".to_string(),
381 Message::DbQueryFailed => "Database query failed".to_string(),
382 Message::DbMigrationFailed => "Database migration failed".to_string(),
383 Message::DatabaseOperationFailed { operation, error } => {
384 format!("Database operation '{}' failed (continuing monitoring): {}", operation, error)
385 }
386 Message::NoIdSet => "No ID set".to_string(),
387
388 Message::FileNotFound => "File not found".to_string(),
390 Message::FileReadError => "Failed to read file".to_string(),
391 Message::FileWriteError => "Failed to write file".to_string(),
392 Message::InvalidPidFileContent => "Invalid PID file content".to_string(),
393 Message::DataStoragePathError => "DataStorage get_path error".to_string(),
394
395 Message::PathConfigured => "PATH successfully configured for system-wide access".to_string(),
397 Message::PathConfigWarning { error } => format!(
398 "Warning: Could not configure PATH automatically. {}\nYou may need to run as administrator or manually add kasl to your PATH.",
399 error
400 ),
401 Message::PathQueryFailed(status) => format!("Failed to query PATH from registry: {:?}", status),
402 Message::PathSetFailed => "Failed to set PATH in registry".to_string(),
403 Message::PathRegistryQueryError { status } => format!("Registry query failed (exit code: {})", status),
404 Message::PathRegistryUpdateError { status, stderr } => {
405 if stderr.trim().is_empty() {
406 format!("Registry update failed (exit code: {})", status)
407 } else {
408 format!("Registry update failed (exit code: {}): {}", status, stderr.trim())
409 }
410 }
411 Message::FailedToJoinPaths => "Failed to join paths".to_string(),
412 Message::FailedToExecuteRegQuery => "Failed to execute reg query".to_string(),
413 Message::FailedToParseRegOutput => "Failed to parse reg query output".to_string(),
414 Message::FailedToGetPathFromReg => "Failed to get PATH value from reg query".to_string(),
415 Message::FailedToExecuteRegSet => "Failed to execute reg set".to_string(),
416 Message::FailedToOpenProcess(code) => format!("Failed to open process: error code {}", code),
417 Message::FailedToTerminateProcess(code) => format!("Failed to terminate process: error code {}", code),
418 Message::ProcessNotFound => "Process doesn't exist".to_string(),
419 Message::ProcessTerminationNotSupported => "Process termination not supported on this platform".to_string(),
420
421 Message::MonthlyProductivity(percentage) => format!("Monthly work productivity: {:.1}%", percentage),
423 Message::LowProductivityWarning { current, threshold } => {
424 format!(
425 "🔴 LOW PRODUCTIVITY: {:.1}% (minimum: {:.1}%)\n If an absence is missing from the day, record it: kasl pauses add --start HH:MM --minutes N",
426 current, threshold
427 )
428 }
429 Message::ProductivityTooLowToSend { current, threshold } => {
430 format!(
431 "Cannot send report: productivity {:.1}% is below minimum {:.1}%\nIf an absence is missing from the day, record it: kasl pauses add --start HH:MM --minutes N",
432 current, threshold
433 )
434 }
435 Message::ManualPauseCreated {
436 start_time,
437 end_time,
438 duration_minutes,
439 } => {
440 format!("Pause recorded: {} - {} ({} minutes)", start_time, end_time, duration_minutes)
441 }
442 Message::ManualPauseOverlaps { start_time, end_time } => {
443 format!("Overlaps an existing pause ({} - {})", start_time, end_time)
444 }
445 Message::ManualPauseRemoved(id) => format!("Pause {} removed", id),
446 Message::ManualPauseNotFound(id) => format!("no pause with id '{}' - see `kasl pauses list`", id),
447 Message::ProductivityRecalculated(percentage) => format!("Productivity recalculated: {:.1}%", percentage),
448
449 Message::EncryptionKeyMustBeSet => "ENCRYPTION_KEY must be set".to_string(),
451 Message::EncryptionIvMustBeSet => "ENCRYPTION_IV must be set".to_string(),
452
453 Message::PromptTaskName => "Enter task name (multi-line paste OK)".to_string(),
455 Message::TaskNameMergedFromPaste => "Merged pasted lines into the task name.".to_string(),
456 Message::PromptTaskComment => "Enter comment".to_string(),
457 Message::PromptTaskCompleteness => "Enter completeness".to_string(),
458 Message::PromptGitlabToken => "Enter your GitLab private token".to_string(),
459 Message::PromptGitlabUrl => "Enter the GitLab API URL".to_string(),
460 Message::PromptJiraLogin => "Enter your Jira login".to_string(),
461 Message::PromptJiraUrl => "Enter the Jira API URL".to_string(),
462 Message::PromptJiraPassword => "Enter your Jira password".to_string(),
463 Message::PromptSiLogin => "Enter your SiServer login".to_string(),
464 Message::PromptSiAuthUrl => "Enter your SiServer login URL".to_string(),
465 Message::PromptSiApiUrl => "Enter the SiServer API URL".to_string(),
466 Message::PromptSiPassword => "Enter your SiServer password".to_string(),
467 Message::PromptMinPauseDuration => "Enter minimum pause duration (minutes)".to_string(),
468 Message::PromptPauseThreshold => "Enter pause threshold (seconds)".to_string(),
469 Message::PromptPollInterval => "Enter poll interval (milliseconds)".to_string(),
470 Message::PromptActivityThreshold => "Enter activity threshold (seconds)".to_string(),
471 Message::PromptMinProductivityThreshold => "Enter minimum productivity threshold (%)".to_string(),
472 Message::PromptWorkdayHours => "Enter expected workday duration (hours)".to_string(),
473 Message::PromptMinWorkdayFraction => "Enter minimum workday fraction before suggesting breaks (0.0-1.0)".to_string(),
474 Message::PromptServerApiUrl => "Enter server API URL".to_string(),
475 Message::PromptServerAuthToken => "Enter server auth token".to_string(),
476 Message::PromptConfirmDelete => "Are you sure you want to delete this item?".to_string(),
477 Message::PromptSelectOptions => "Select options".to_string(),
478 Message::PromptSelectModules => "Select nodes to configure".to_string(),
479 Message::PromptSelectTasks => "Select tasks".to_string(),
480 Message::PromptSelectTasksToEdit => "Select tasks to edit".to_string(),
481 Message::PromptSelectTasksToImport => "Select tasks to import".to_string(),
482 Message::PromptSelectTasksToIgnore => "Select tasks to ignore (optional)".to_string(),
483 Message::PromptSelectIgnoreNamesToRemove => "Select ignore names to remove (optional)".to_string(),
484 Message::PromptAddIgnoreName => "Add ignore name (empty to finish)".to_string(),
485
486 Message::OperationCompleted => "Operation completed successfully".to_string(),
488 Message::OperationCancelled => "Operation cancelled".to_string(),
489 Message::DataExported => "Data exported successfully".to_string(),
490 Message::BackupCreated => "Backup created successfully".to_string(),
491 Message::InvalidInput => "Invalid input provided".to_string(),
492 Message::PermissionDenied => "Permission denied".to_string(),
493
494 Message::ErrorSendingEvents(error) => format!("[kasl] Error sending events: {}", error),
496 Message::ErrorSendingMonthlyReport(error) => format!("[kasl] Error sending monthly report: {}", error),
497 Message::ErrorInRdevListener(error) => format!("Error in rdev listener: {:?}", error),
498 Message::ErrorRequestingRestDates(error) => format!("Error requesting rest dates: {}", error),
499
500 Message::SelectingTask(name) => format!("Selected task: {}", name),
502 Message::SelectedTaskFormat(name, completeness) => format!("{} - {}%", name, completeness),
503
504 Message::JiraInboxRequiresJiraConfig => "Jira inbox requires Jira to be configured. Run `kasl init` and select Jira.".to_string(),
506 Message::JiraInboxEmpty => "Jira inbox is empty.".to_string(),
507 Message::JiraInboxListHeader => "Jira inbox:".to_string(),
508 Message::JiraInboxSynced { fetched, new_count, updated } => {
509 format!("Jira inbox synced: {} fetched, {} new, {} updated.", fetched, new_count, updated)
510 }
511 Message::JiraInboxNewIssues(count) => format!("Jira inbox: {} new issue(s).", count),
512 Message::JiraInboxNotFound(key) => format!("Issue '{}' not found in inbox.", key),
513 Message::JiraInboxPinned(key) => format!("Pinned {}.", key),
514 Message::JiraInboxUnpinned(key) => format!("Unpinned {}.", key),
515 Message::JiraInboxDismissed(key) => format!("Dismissed {}.", key),
516 Message::JiraInboxOpened(key) => format!("Opened {} in browser.", key),
517 Message::JiraInboxTaken(key) => format!("Imported {} into tasks.", key),
518 Message::JiraInboxOpenFailed(err) => format!("Failed to open browser: {}", err),
519 Message::PromptJiraInboxEnabled => "Enable Jira inbox polling?".to_string(),
520 Message::PromptJiraInboxPollInterval => "Jira inbox poll interval (seconds)".to_string(),
521 Message::PromptJiraInboxNotify => "Show toast notifications for new issues?".to_string(),
522 Message::PromptJiraInboxSortFieldId => "Sort field id for ranking (e.g. customfield_12345 for Scoring; empty to skip)".to_string(),
523 Message::PromptJiraInboxSortFieldLabel => "Label for sort field (default Scoring)".to_string(),
524 Message::PromptJiraInboxExtraFieldId => "Additional custom field id to fetch (empty to finish)".to_string(),
525 Message::PromptJiraInboxExtraFieldLabel => "Label for this custom field".to_string(),
526
527 Message::MigrationsFound(count) => format!("Found {} pending database migrations", count),
529 Message::RunningMigration(version, name) => format!("Running migration v{}: {}", version, name),
530 Message::MigrationCompleted(version) => format!("✓ Migration v{} completed", version),
531 Message::MigrationFailed(version, error) => format!("✗ Migration v{} failed: {}", version, error),
532 Message::AllMigrationsCompleted => "All database migrations completed successfully".to_string(),
533 Message::DatabaseVersion(version) => format!("Current database version: {}", version),
534 Message::DatabaseUpToDate => "Database schema is up to date".to_string(),
535 Message::DatabaseNeedsUpdate => "Database schema needs to be updated".to_string(),
536 Message::MigrationHistory => "Migration history:".to_string(),
537 Message::NothingToRollback => "Nothing to rollback".to_string(),
538 Message::RollingBack(from, to) => format!("Rolling back from v{} to v{}", from, to),
539 Message::RollbackCompleted(version) => format!("Rollback to v{} completed", version),
540 };
541
542 write!(f, "{}", text)
543 }
544}