1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub enum HistoryAction {
6 Set {
7 name: String,
8 old_value: Option<String>,
9 new_value: String,
10 },
11 Delete {
12 name: String,
13 old_value: String,
14 },
15 BatchUpdate {
16 changes: Vec<(String, Option<String>, String)>,
17 },
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct HistoryEntry {
22 pub id: uuid::Uuid,
23 pub timestamp: DateTime<Utc>,
24 pub action: HistoryAction,
25}
26
27impl HistoryEntry {
28 #[must_use]
29 pub fn new(action: HistoryAction) -> Self {
30 Self {
31 id: uuid::Uuid::new_v4(),
32 timestamp: Utc::now(),
33 action,
34 }
35 }
36}
37
38#[derive(Debug, Default)]
39pub struct History {
40 entries: Vec<HistoryEntry>,
41 max_entries: usize,
42}
43
44impl History {
45 #[must_use]
46 pub const fn new(max_entries: usize) -> Self {
47 Self {
48 entries: Vec::new(),
49 max_entries,
50 }
51 }
52
53 pub fn add(&mut self, entry: HistoryEntry) {
54 self.entries.push(entry);
55 if self.entries.len() > self.max_entries {
56 self.entries.remove(0);
57 }
58 }
59
60 #[must_use]
61 pub fn recent(&self, count: usize) -> Vec<&HistoryEntry> {
62 self.entries.iter().rev().take(count).collect()
63 }
64
65 pub fn clear(&mut self) {
66 self.entries.clear();
67 }
68}