Skip to main content

jobberdb/
operation.rs

1//! Operations that can be processed at a jobber database.
2
3use super::prelude::*;
4use rand::Rng;
5
6const MOTD: &[&str] = &["And don't work too much!", "Work smarter, not harder."];
7
8/// Catches what to change the jobs within the database.
9#[derive(Clone, Debug)]
10pub enum Operation {
11    /// No operation
12    None,
13    /// No change
14    Intro,
15    /// Push a new `Job` into database.
16    Push(usize, Job),
17    /// Change an existing `Job` at index `usize` into database but return error if message is missing.
18    Modify(usize, Job),
19    /// Remove jobs from
20    Delete(Positions),
21    /// Import file
22    Import(String, usize, TagSet),
23    /// Change configuration
24    Configure(Option<TagSet>, Properties),
25    /// List jobs
26    List(Positions, Range, Option<TagSet>),
27    /// Report jobs
28    Report(Positions, Range, Option<TagSet>),
29    /// Export jobs
30    ExportCSV(Positions, Range, Option<TagSet>, Columns),
31    /// List all available tags.
32    ListTags(TagSet),
33    /// Show the database configuration.
34    ShowConfiguration(Configuration),
35}
36
37impl Operation {
38    pub fn reports_open_job(&self) -> bool {
39        matches!(self, Operation::Intro | Operation::Push(_, _))
40    }
41}
42
43impl std::fmt::Display for Operation {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        match self {
46            Operation::None => Ok(()),
47            Operation::Intro => {
48                let mut rng = rand::thread_rng();
49                let motd = MOTD[rng.gen_range(0..MOTD.len())];
50                write!(f, "\n{}", motd)
51            }
52            Operation::Push(position, job) => {
53                if job.is_open() {
54                    write!(f, "Started new job:\n\n    Pos: {}\n{job}", position + 1)
55                } else {
56                    write!(f, "Added new job:\n\n    Pos: {}\n{job}", position + 1)
57                }
58            }
59            Operation::Modify(position, job) => {
60                if job.is_open() {
61                    write!(f, "Modified open job:\n\n    Pos: {}\n{job}", position + 1)
62                } else {
63                    write!(f, "Modified job:\n\n    Pos: {}\n{job}", position + 1)
64                }
65            }
66            Operation::Delete(positions) => {
67                write!(
68                    f,
69                    "Deleting job(s) at position(s): {}",
70                    positions.into_ranges()
71                )
72            }
73            Operation::Import(filename, count, new_tags) => {
74                if new_tags.is_empty() {
75                    write!(f, "Imported {count} jobs from {filename}.")
76                } else {
77                    write!(
78                        f,
79                        "Imported {count} jobs from {filename} (added new tags {new_tags})."
80                    )
81                }
82            }
83            Operation::Configure(tags, config) => {
84                if let Some(tags) = tags {
85                    write!(
86                        f,
87                        "Changed the following configuration values for tag(s) {}:\n\n{}",
88                        tags, config
89                    )
90                } else {
91                    write!(
92                        f,
93                        "Changed the following default configuration values:\n\n{}",
94                        config
95                    )
96                }
97            }
98            Operation::List(_, range, tags) => {
99                if let Some(tags) = tags {
100                    write!(f, "Listed {range} with tags {tags}.")?;
101                } else {
102                    write!(f, "Listed {range}:")?;
103                }
104                Ok(())
105            }
106            Operation::Report(_, range, tags) => {
107                if let Some(tags) = tags {
108                    write!(f, "Reported {range} with tags {tags}.")?;
109                } else {
110                    write!(f, "Reported {range}:")?;
111                }
112                Ok(())
113            }
114            Operation::ExportCSV(_, range, tags, columns) => {
115                if let Some(tags) = tags {
116                    write!(f, "Exported {columns} from {range} with tags {tags}.")?;
117                } else {
118                    write!(f, "Exported {columns} from {range}:")?;
119                }
120                Ok(())
121            }
122            Operation::ListTags(tags) => {
123                if tags.is_empty() {
124                    write!(f, "Currently no tags are used.")
125                } else {
126                    write!(f, "Known tags: {}", tags)
127                }
128            }
129            Operation::ShowConfiguration(configuration) => {
130                // print base configurations
131                writeln!(f, "Base Configuration:\n\n{}", configuration.base)?;
132                // print tag wise configurations
133                for (tag, properties) in &configuration.tags {
134                    write!(
135                        f,
136                        "Configuration for tag {}:\n\n{}",
137                        TagSet::from(tag.as_str()),
138                        properties
139                    )?;
140                }
141                Ok(())
142            }
143        }
144    }
145}