@@ -86,6 +86,19 @@ struct ListArgs {
8686 /// Include only ereports collected after this timestamp
8787 #[ clap( long, short) ]
8888 after : Option < DateTime < Utc > > ,
89+
90+ /// Filter ereports based on whether or not their database records have
91+ /// been marked as "seen" (included in a committed sitrep).
92+ ///
93+ /// Note that ereports which have not been marked in the database *may*
94+ /// still have been included in a sitrep. Marking of ereport database
95+ /// records occurs in the background, and may not be up to date with the
96+ /// latest sitrep. If an ereport has been marked as seen, it has
97+ /// *definitely* been included in a committed sitrep, but if an ereport
98+ /// has not been marked, it *may or may not* have been included in a
99+ /// committed sitrep.
100+ #[ clap( long = "seen" , short = 'm' , value_enum, default_value_t) ]
101+ seen : Seen ,
89102}
90103
91104#[ derive( Debug , Args , Clone ) ]
@@ -99,6 +112,21 @@ struct ReportersArgs {
99112 serial : Option < String > ,
100113}
101114
115+ #[ derive(
116+ Copy , Clone , Debug , Default , PartialEq , Eq , PartialOrd , Ord , clap:: ValueEnum ,
117+ ) ]
118+ enum Seen {
119+ /// Include all ereports, regardless of whether or not they have been
120+ /// marked.
121+ #[ default]
122+ All ,
123+ /// Include only ereports whose database records have been marked as seen.
124+ Marked ,
125+ /// Include only ereports whose database records have NOT been marked as
126+ /// seen.
127+ Unmarked ,
128+ }
129+
102130pub ( super ) async fn cmd_db_ereport (
103131 datastore : & DataStore ,
104132 fetch_opts : & DbFetchOptions ,
@@ -138,6 +166,22 @@ async fn cmd_db_ereport_list(
138166 serial : Option < & ' report str > ,
139167 #[ tabled( display_with = "display_option_blank" , rename = "P/N" ) ]
140168 part_number : Option < & ' report str > ,
169+
170+ /// The underlying ereport record. This is not displayed when
171+ /// formatting, but is retained so that the `EreportRow` can be
172+ /// converted into an `EreportRowWithMark` if the markedness is needed.
173+ #[ tabled( skip) ]
174+ ereport : & ' report db:: model:: Ereport ,
175+ }
176+
177+ /// Adds a `MARK` column to `EreportRow` to indicate whether or not the
178+ /// ereport has been marked as seen in the database.
179+ #[ derive( Tabled ) ]
180+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
181+ struct EreportRowWithMark < ' report > {
182+ mark : & ' static str ,
183+ #[ tabled( inline) ]
184+ ereport : EreportRow < ' report > ,
141185 }
142186
143187 impl < ' report > From < & ' report db:: model:: Ereport > for EreportRow < ' report > {
@@ -169,10 +213,27 @@ async fn cmd_db_ereport_list(
169213 source,
170214 serial : serial_number. as_deref ( ) ,
171215 part_number : part_number. as_deref ( ) ,
216+ ereport,
172217 }
173218 }
174219 }
175220
221+ impl < ' report > From < EreportRow < ' report > > for EreportRowWithMark < ' report > {
222+ fn from ( row : EreportRow < ' report > ) -> Self {
223+ // The column is named "MARK" and its values are either "seen" or
224+ // "", because I wanted to make it as obvious as possible that an
225+ // unmarked ereport may still have been seen in a sitrep. The more
226+ // obvious option of a "SEEN" column with values "yes" and "no" is
227+ // potentially misleading, as "no" would suggest the ereport has not
228+ // been seen, when actually it has not been *marked*. So, the column
229+ // is named "MARK". But, I wanted to include the word "seen", so
230+ // marked-as-seen ereports have the value "seen".
231+ let mark =
232+ if row. ereport . marked_seen_in . is_some ( ) { "seen" } else { "" } ;
233+ Self { mark, ereport : row }
234+ }
235+ }
236+
176237 if let ( Some ( before) , Some ( after) ) = ( args. before , args. after ) {
177238 anyhow:: ensure!(
178239 after < before,
@@ -213,6 +274,12 @@ async fn cmd_db_ereport_list(
213274 query = query. filter ( dsl:: time_deleted. is_null ( ) ) ;
214275 }
215276
277+ match args. seen {
278+ Seen :: Marked => query = query. filter ( dsl:: marked_seen_in. is_not_null ( ) ) ,
279+ Seen :: Unmarked => query = query. filter ( dsl:: marked_seen_in. is_null ( ) ) ,
280+ Seen :: All => { }
281+ }
282+
216283 let ereports = query. load_async ( & * conn) . await . with_context ( ctx) ?;
217284 check_limit ( & ereports, fetch_opts. fetch_limit , ctx) ;
218285
@@ -229,7 +296,13 @@ async fn cmd_db_ereport_list(
229296 )
230297 } ) ;
231298
232- let mut table = tabled:: Table :: new ( rows) ;
299+ let mut table = if args. seen == Seen :: All {
300+ // If both marked and unmarked ereports were included, add the "mark"
301+ // column.
302+ tabled:: Table :: new ( rows. into_iter ( ) . map ( EreportRowWithMark :: from) )
303+ } else {
304+ tabled:: Table :: new ( rows)
305+ } ;
233306 table
234307 . with ( tabled:: settings:: Style :: empty ( ) )
235308 . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) ) ;
0 commit comments