1use std::collections::HashMap;
7
8use metatheca::Uuid;
9
10use crate::error::Result;
11
12pub struct JotRow {
14 pub entry: Uuid,
15 pub profile: String,
16 pub id: i64,
17 pub ext: String,
18 pub created_at_ns: Option<i64>,
19 pub summary: String,
22 pub effective: cuj::facts::EffectiveIndex,
23 pub attachments: Vec<String>,
25}
26
27impl JotRow {
28 pub fn short_ref(&self, scope: Option<&str>) -> String {
31 match scope {
32 Some(p) if p == self.profile => format!("--{}", self.id),
33 _ => format!("--{}--{}", self.profile, self.id),
34 }
35 }
36}
37
38pub struct Snapshot {
39 pub rows: Vec<JotRow>,
41 pub by_entry: HashMap<Uuid, usize>,
42 pub by_ident: HashMap<(String, i64), usize>,
43 owner: HashMap<Uuid, Uuid>,
46 pub profiles: Vec<(String, usize)>,
48 pub configs: HashMap<String, cuj::facts::ProfileConfig>,
51}
52
53impl Snapshot {
54 pub fn build(app: &cuj::App) -> Result<Snapshot> {
55 let reads = app.reads(&cuj::Opts::default())?;
56 let mut rows = Vec::new();
57 for (entry, ident) in reads.list(None) {
58 let summary = cuj::queries::summary_line(&reads, entry);
59 let attachments = reads
60 .attachments_of(entry)
61 .iter()
62 .map(|(_, a)| a.filename.clone())
63 .collect();
64 rows.push(JotRow {
65 entry,
66 profile: ident.profile.clone(),
67 id: ident.id,
68 ext: ident.ext.clone(),
69 created_at_ns: reads.births.get(&entry).map(|b| b.created_at_ns),
70 summary,
71 effective: reads.effective(entry),
72 attachments,
73 });
74 }
75 let by_entry: HashMap<Uuid, usize> =
76 rows.iter().enumerate().map(|(i, r)| (r.entry, i)).collect();
77 let by_ident: HashMap<(String, i64), usize> = rows
78 .iter()
79 .enumerate()
80 .map(|(i, r)| ((r.profile.clone(), r.id), i))
81 .collect();
82
83 let mut owner = HashMap::new();
84 for (att_entry, att) in &reads.attachments {
85 if let Ok(jot) = Uuid::parse_str(&att.jot) {
86 owner.insert(*att_entry, jot);
87 }
88 }
89 for (x_entry, body, _) in &reads.extractions {
90 if let Some(jot) = Uuid::parse_str(&body.of)
91 .ok()
92 .and_then(|att| owner.get(&att).copied())
93 {
94 owner.insert(*x_entry, jot);
95 }
96 }
97
98 let mut profiles: Vec<(String, usize)> = reads
100 .profiles
101 .keys()
102 .map(|name| {
103 let n = rows.iter().filter(|r| &r.profile == name).count();
104 (name.clone(), n)
105 })
106 .collect();
107 profiles.sort();
108 let configs = reads
109 .profiles
110 .iter()
111 .map(|(name, (_, cfg))| (name.clone(), cfg.clone()))
112 .collect();
113
114 Ok(Snapshot {
115 rows,
116 by_entry,
117 by_ident,
118 owner,
119 profiles,
120 configs,
121 })
122 }
123
124 pub fn owning_row(&self, entry: Uuid) -> Option<usize> {
127 if let Some(i) = self.by_entry.get(&entry) {
128 return Some(*i);
129 }
130 self.owner
131 .get(&entry)
132 .and_then(|jot| self.by_entry.get(jot))
133 .copied()
134 }
135}
136