Skip to content

Commit 3041af0

Browse files
committed
feat: maintain selected row across filtering
1 parent d46034e commit 3041af0

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

src/app/data.rs

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,17 @@ impl Data {
201201
}
202202

203203
pub fn unfilter(&mut self) {
204-
self.selected_row = None;
204+
let previous_real_index_selected = self.selected_row.map(|x| self.get_real_index(x));
205205
self.filtered_rows = None;
206+
if let Some(old_selected) = previous_real_index_selected {
207+
self.selected_row = Some(old_selected);
208+
}
206209
}
207210

208211
pub fn apply_filter(&mut self, common_fields: &BTreeSet<String>) {
209212
if let Some(filter) = self.filter.as_ref() {
210-
self.selected_row = None; // TODO 3: Update selected if still included in displayed rows
213+
let previous_real_index_selected = self.selected_row.map(|x| self.get_real_index(x));
214+
211215
self.filtered_rows = Some(
212216
self.rows
213217
.iter_mut()
@@ -221,6 +225,11 @@ impl Data {
221225
})
222226
.collect(),
223227
);
228+
if let Some(old_selected) = previous_real_index_selected {
229+
if let Some(filtered) = self.filtered_rows.as_ref() {
230+
self.selected_row = filtered.iter().position(|&idx| idx == old_selected);
231+
}
232+
}
224233
} else {
225234
warn!("Apply called but no filter is available")
226235
}
@@ -475,4 +484,88 @@ mod tests {
475484
insta_settings.bind(|| insta::assert_yaml_snapshot!(data));
476485
}
477486
}
487+
488+
#[test]
489+
fn selected_maintenance_with_filtering() {
490+
let test_field = String::from("test field");
491+
let rows = (5..10)
492+
.map(|i| {
493+
let mut row = create_log_row_no_extra();
494+
row.data.insert(test_field.clone(), i.into());
495+
row
496+
})
497+
.collect();
498+
let mut data = Data {
499+
rows,
500+
..Default::default()
501+
};
502+
let display_options = DataDisplayOptions::default();
503+
let common_fields = display_options.common_fields();
504+
505+
// Set "7" as selected
506+
data.selected_row = Some(2);
507+
508+
// Save selected row from before
509+
let expected = data
510+
.selected_row_data_as_slice(common_fields)
511+
.unwrap()
512+
.to_vec();
513+
514+
data.filter = Some(FilterConfig {
515+
search_key: "7".to_string(),
516+
..Default::default()
517+
});
518+
data.apply_filter(DataDisplayOptions::default().common_fields());
519+
520+
// Test that 7 is still selected
521+
let actual = data
522+
.selected_row_data_as_slice(common_fields)
523+
.unwrap()
524+
.to_vec();
525+
526+
assert_eq!(actual, expected);
527+
528+
// Then reverse
529+
data.unfilter();
530+
531+
// Test that 7 is still selected
532+
let actual = data
533+
.selected_row_data_as_slice(common_fields)
534+
.unwrap()
535+
.to_vec();
536+
537+
assert_eq!(actual, expected);
538+
}
539+
540+
#[test]
541+
fn selected_unselected_when_not_present() {
542+
let test_field = String::from("test field");
543+
let rows = (5..10)
544+
.map(|i| {
545+
let mut row = create_log_row_no_extra();
546+
row.data.insert(test_field.clone(), i.into());
547+
row
548+
})
549+
.collect();
550+
let mut data = Data {
551+
rows,
552+
..Default::default()
553+
};
554+
let display_options = DataDisplayOptions::default();
555+
let common_fields = display_options.common_fields();
556+
557+
// Set "7" as selected
558+
data.selected_row = Some(2);
559+
560+
// Filter for 6, so 7 is not included
561+
data.filter = Some(FilterConfig {
562+
search_key: "6".to_string(),
563+
..Default::default()
564+
});
565+
data.apply_filter(DataDisplayOptions::default().common_fields());
566+
567+
let actual = data.selected_row_data_as_slice(common_fields);
568+
569+
assert!(actual.is_none());
570+
}
478571
}

0 commit comments

Comments
 (0)