rusticity_term/efs/
actions.rs1use crate::app::App;
2use crate::common::{ColumnId, InputFocus, PageSize};
3use crate::ui::efs::{
4 filtered_access_points, filtered_efs_file_systems, DetailTab, FILTER_CONTROLS,
5};
6
7fn ap_col_count(app: &App) -> usize {
9 app.efs_state.ap_column_ids.len()
10}
11
12fn mt_col_count(app: &App) -> usize {
14 app.efs_state.mt_column_ids.len()
15}
16
17fn toggle_visible(visible: &mut Vec<ColumnId>, all: &[ColumnId], idx: usize) {
19 if idx > 0 && idx <= all.len() {
20 let col = all[idx - 1];
21 if let Some(pos) = visible.iter().position(|c| *c == col) {
22 if visible.len() > 1 {
23 visible.remove(pos);
24 }
25 } else {
26 visible.push(col);
27 }
28 }
29}
30
31fn set_page_size_by_idx<T>(table: &mut crate::table::TableState<T>, idx: usize, n: usize) {
34 let ps = if idx == n + 3 {
35 PageSize::Ten
36 } else if idx == n + 4 {
37 PageSize::TwentyFive
38 } else if idx == n + 5 {
39 PageSize::Fifty
40 } else if idx == n + 6 {
41 PageSize::OneHundred
42 } else {
43 return;
44 };
45 table.set_page_size(ps);
46}
47
48pub fn next_item(app: &mut App) {
51 if app.efs_state.current_file_system.is_some() {
52 match app.efs_state.detail_tab {
53 DetailTab::Tags => {
54 let tag_count = current_fs_tag_count(app);
55 if tag_count > 0 {
56 app.efs_state.tags_table.next_item(tag_count);
57 }
58 }
59 DetailTab::AccessPoints => {
60 let n = filtered_access_points(app).len();
61 if n > 0 {
62 app.efs_state.access_points.next_item(n);
63 }
64 }
65 DetailTab::Network => {
66 let n = app.efs_state.mount_targets.items.len();
67 if n > 0 {
68 app.efs_state.mount_targets.next_item(n);
69 }
70 }
71 _ => {}
72 }
73 } else {
74 let filtered = filtered_efs_file_systems(app);
75 if !filtered.is_empty() {
76 app.efs_state.file_systems.next_item(filtered.len());
77 }
78 }
79}
80
81fn current_fs_tag_count(app: &App) -> usize {
82 app.efs_state
83 .current_file_system
84 .as_deref()
85 .and_then(|id| {
86 app.efs_state
87 .file_systems
88 .items
89 .iter()
90 .find(|f| f.file_system_id == id)
91 })
92 .map(|fs| fs.tags.len())
93 .unwrap_or(0)
94}
95
96pub fn prev_item(app: &mut App) {
97 if app.efs_state.current_file_system.is_some() {
98 match app.efs_state.detail_tab {
99 DetailTab::Tags => app.efs_state.tags_table.prev_item(),
100 DetailTab::AccessPoints => app.efs_state.access_points.prev_item(),
101 DetailTab::Network => app.efs_state.mount_targets.prev_item(),
102 _ => {}
103 }
104 } else {
105 app.efs_state.file_systems.prev_item();
106 }
107}
108
109pub fn page_down_filter_input(app: &mut App) {
110 if app.efs_state.current_file_system.is_some()
111 && app.efs_state.detail_tab == DetailTab::AccessPoints
112 {
113 let n = filtered_access_points(app).len();
114 app.efs_state.access_points.page_down(n);
115 return;
116 }
117 if app.efs_state.input_focus == InputFocus::Filter {
118 let filtered = filtered_efs_file_systems(app);
119 app.efs_state.file_systems.page_down(filtered.len());
120 } else {
121 let page_size = app.efs_state.file_systems.page_size.value();
122 let filtered_count = filtered_efs_file_systems(app).len();
123 app.efs_state.input_focus.handle_page_down(
124 &mut app.efs_state.file_systems.selected,
125 &mut app.efs_state.file_systems.scroll_offset,
126 page_size,
127 filtered_count,
128 );
129 }
130}
131
132pub fn page_down_normal(app: &mut App) {
133 if app.efs_state.current_file_system.is_some() {
134 match app.efs_state.detail_tab {
135 DetailTab::AccessPoints => {
136 let n = filtered_access_points(app).len();
137 app.efs_state.access_points.page_down(n);
138 }
139 DetailTab::Network => {
140 let n = app.efs_state.mount_targets.items.len();
141 app.efs_state.mount_targets.page_down(n);
142 }
143 _ => {}
144 }
145 return;
146 }
147 let filtered = filtered_efs_file_systems(app);
148 app.efs_state.file_systems.page_down(filtered.len());
149}
150
151pub fn page_up_filter_input(app: &mut App) {
152 if app.efs_state.current_file_system.is_some()
153 && app.efs_state.detail_tab == DetailTab::AccessPoints
154 {
155 app.efs_state.access_points.page_up();
156 return;
157 }
158 if app.efs_state.input_focus == InputFocus::Filter {
159 app.efs_state.file_systems.page_up();
160 } else {
161 let page_size = app.efs_state.file_systems.page_size.value();
162 app.efs_state.input_focus.handle_page_up(
163 &mut app.efs_state.file_systems.selected,
164 &mut app.efs_state.file_systems.scroll_offset,
165 page_size,
166 );
167 }
168}
169
170pub fn page_up_normal(app: &mut App) {
171 if app.efs_state.current_file_system.is_some() {
172 match app.efs_state.detail_tab {
173 DetailTab::AccessPoints => app.efs_state.access_points.page_up(),
174 DetailTab::Network => app.efs_state.mount_targets.page_up(),
175 _ => {}
176 }
177 return;
178 }
179 app.efs_state.file_systems.page_up();
180}
181
182pub fn expand_row(app: &mut App) {
183 if app.efs_state.current_file_system.is_some() {
184 match app.efs_state.detail_tab {
185 DetailTab::Tags => app.efs_state.tags_table.toggle_expand(),
186 DetailTab::AccessPoints => app.efs_state.access_points.toggle_expand(),
187 DetailTab::Network => app.efs_state.mount_targets.toggle_expand(),
188 _ => {}
189 }
190 } else {
191 app.efs_state.file_systems.toggle_expand();
192 }
193}
194
195pub fn prev_pane(app: &mut App) {
196 collapse_row(app);
197}
198
199pub fn collapse_row(app: &mut App) {
200 if app.efs_state.current_file_system.is_some() {
201 match app.efs_state.detail_tab {
202 DetailTab::Tags => app.efs_state.tags_table.collapse(),
203 DetailTab::AccessPoints => app.efs_state.access_points.collapse(),
204 DetailTab::Network => app.efs_state.mount_targets.collapse(),
205 _ => {}
206 }
207 } else {
208 app.efs_state.file_systems.collapse();
209 }
210}
211
212pub fn go_to_page(app: &mut App, page: usize) {
213 if app.efs_state.current_file_system.is_some()
214 && app.efs_state.detail_tab == DetailTab::AccessPoints
215 {
216 let n = filtered_access_points(app).len();
217 app.efs_state.access_points.goto_page(page, n);
218 return;
219 }
220 let filtered_count = filtered_efs_file_systems(app).len();
221 app.efs_state.file_systems.goto_page(page, filtered_count);
222}
223
224pub fn get_active_filter_mut(app: &mut App) -> Option<&mut String> {
227 if app.efs_state.current_file_system.is_some()
228 && app.efs_state.detail_tab == DetailTab::AccessPoints
229 {
230 return Some(&mut app.efs_state.access_points.filter);
231 }
232 Some(&mut app.efs_state.file_systems.filter)
233}
234
235pub fn apply_filter_reset(app: &mut App) {
236 if app.efs_state.current_file_system.is_some()
237 && app.efs_state.detail_tab == DetailTab::AccessPoints
238 {
239 app.efs_state.access_points.reset();
240 return;
241 }
242 app.efs_state.file_systems.reset();
243}
244
245pub fn start_filter(app: &mut App) {
246 app.efs_state.input_focus = InputFocus::Filter;
247}
248
249pub fn next_filter_focus(app: &mut App) {
250 app.efs_state.input_focus = app.efs_state.input_focus.next(&FILTER_CONTROLS);
251}
252
253pub fn prev_filter_focus(app: &mut App) {
254 app.efs_state.input_focus = app.efs_state.input_focus.prev(&FILTER_CONTROLS);
255}
256
257pub fn is_pagination_focused(app: &App) -> bool {
258 app.efs_state.input_focus == InputFocus::Pagination
259}
260
261pub fn yank(app: &App) {
264 use crate::app::copy_to_clipboard;
265 if let Some(fs_id) = &app.efs_state.current_file_system {
266 if app.efs_state.detail_tab == crate::ui::efs::DetailTab::FileSystemPolicy
268 && !app.efs_state.policy_document.is_empty()
269 {
270 copy_to_clipboard(&app.efs_state.policy_document);
271 return;
272 }
273 if let Some(fs) = app
275 .efs_state
276 .file_systems
277 .items
278 .iter()
279 .find(|f| &f.file_system_id == fs_id)
280 {
281 copy_to_clipboard(&fs.file_system_arn);
282 }
283 } else {
284 let filtered = filtered_efs_file_systems(app);
286 if let Some(fs) = app.efs_state.file_systems.get_selected(&filtered) {
287 copy_to_clipboard(&fs.file_system_id);
288 }
289 }
290}
291
292pub fn select_item(app: &mut App) {
295 if app.efs_state.current_file_system.is_none() {
296 let filtered = filtered_efs_file_systems(app);
297 if let Some(fs) = app.efs_state.file_systems.get_selected(&filtered) {
298 app.efs_state.current_file_system = Some(fs.file_system_id.clone());
299 app.efs_state.detail_tab = crate::ui::efs::DetailTab::MeteredSize;
300 }
301 }
302}
303
304pub fn go_back(app: &mut App) {
305 app.efs_state.current_file_system = None;
306 app.efs_state.detail_tab = crate::ui::efs::DetailTab::MeteredSize;
307}
308
309pub fn next_detail_tab(app: &mut App) {
310 use crate::common::CyclicEnum;
311 app.efs_state.detail_tab = app.efs_state.detail_tab.next();
312 trigger_tab_load(app);
313}
314
315pub fn prev_detail_tab(app: &mut App) {
316 use crate::common::CyclicEnum;
317 app.efs_state.detail_tab = app.efs_state.detail_tab.prev();
318 trigger_tab_load(app);
319}
320
321fn trigger_tab_load(app: &mut App) {
325 use crate::ui::monitoring::MonitoringState;
326 match app.efs_state.detail_tab {
327 crate::ui::efs::DetailTab::Monitoring => {
328 app.efs_state.set_metrics_loading(true);
329 app.efs_state.set_monitoring_scroll(0);
330 app.efs_state.clear_metrics();
331 }
332 crate::ui::efs::DetailTab::FileSystemPolicy => {
333 app.efs_state.policy_loading = true;
334 app.efs_state.policy_scroll = 0;
335 }
336 crate::ui::efs::DetailTab::AccessPoints => {
337 app.efs_state.ap_loading = true;
338 app.efs_state.access_points.reset();
339 }
340 crate::ui::efs::DetailTab::Network => {
341 app.efs_state.mt_loading = true;
342 app.efs_state.mount_targets.reset();
343 }
344 crate::ui::efs::DetailTab::Replication => {
345 app.efs_state.replication_loading = true;
346 }
347 _ => {}
348 }
349}
350
351const EFS_MONITORING_CHARTS: usize = 6;
354
355pub fn scroll_down_detail(app: &mut App) {
357 use crate::ui::monitoring::MonitoringState;
358 match app.efs_state.detail_tab {
359 crate::ui::efs::DetailTab::Monitoring => {
360 let max = EFS_MONITORING_CHARTS.saturating_sub(1);
361 app.efs_state
362 .set_monitoring_scroll((app.efs_state.monitoring_scroll() + 1).min(max));
363 }
364 crate::ui::efs::DetailTab::FileSystemPolicy => {
365 let max = app
366 .efs_state
367 .policy_document
368 .lines()
369 .count()
370 .saturating_sub(1);
371 app.efs_state.policy_scroll = (app.efs_state.policy_scroll + 1).min(max);
372 }
373 _ => {}
374 }
375}
376
377pub fn scroll_up_detail(app: &mut App) {
379 use crate::ui::monitoring::MonitoringState;
380 match app.efs_state.detail_tab {
381 crate::ui::efs::DetailTab::Monitoring => {
382 app.efs_state
383 .set_monitoring_scroll(app.efs_state.monitoring_scroll().saturating_sub(1));
384 }
385 crate::ui::efs::DetailTab::FileSystemPolicy => {
386 app.efs_state.policy_scroll = app.efs_state.policy_scroll.saturating_sub(1);
387 }
388 _ => {}
389 }
390}
391
392pub fn breadcrumb(app: &App) -> Vec<String> {
393 let mut parts = vec!["EFS".to_string()];
394 if let Some(fs_id) = &app.efs_state.current_file_system {
395 parts.push(fs_id.clone());
396 } else {
397 parts.push("File Systems".to_string());
398 }
399 parts
400}
401
402pub fn console_url(app: &App) -> String {
403 use crate::efs;
404 if let Some(fs_id) = &app.efs_state.current_file_system {
406 return efs::console_url_file_system_with_tab(
407 &app.config.region,
408 fs_id,
409 app.efs_state.detail_tab,
410 );
411 }
412 let filtered = filtered_efs_file_systems(app);
413 if let Some(fs) = app.efs_state.file_systems.get_selected(&filtered) {
414 efs::console_url_file_system(&app.config.region, &fs.file_system_id)
415 } else {
416 efs::console_url_file_systems(&app.config.region)
417 }
418}
419
420pub fn toggle_column(app: &mut App) {
423 let idx = app.column_selector_index;
424 if app.efs_state.current_file_system.is_some() {
425 match app.efs_state.detail_tab {
426 DetailTab::Tags => {
427 set_page_size_by_idx(&mut app.efs_state.tags_table, idx, 2);
429 return;
430 }
431 DetailTab::AccessPoints => {
432 let all = app.efs_state.ap_column_ids.clone();
433 toggle_visible(&mut app.efs_state.ap_visible_column_ids, &all, idx);
434 set_page_size_by_idx(&mut app.efs_state.access_points, idx, all.len());
435 return;
436 }
437 DetailTab::Network => {
438 let all = app.efs_state.mt_column_ids.clone();
439 toggle_visible(&mut app.efs_state.mt_visible_column_ids, &all, idx);
440 set_page_size_by_idx(&mut app.efs_state.mount_targets, idx, all.len());
441 return;
442 }
443 _ => return,
444 }
445 }
446 if idx > 0 && idx <= app.efs_column_ids.len() {
448 if let Some(col) = app.efs_column_ids.get(idx - 1) {
449 if let Some(pos) = app.efs_visible_column_ids.iter().position(|c| c == col) {
450 if app.efs_visible_column_ids.len() > 1 {
451 app.efs_visible_column_ids.remove(pos);
452 }
453 } else {
454 app.efs_visible_column_ids.push(*col);
455 }
456 }
457 } else {
458 set_page_size_by_idx(
459 &mut app.efs_state.file_systems,
460 idx,
461 app.efs_column_ids.len(),
462 );
463 }
464}
465
466fn active_prefs_col_count(app: &App) -> usize {
468 if app.efs_state.current_file_system.is_some() {
469 match app.efs_state.detail_tab {
470 DetailTab::Tags => 2,
471 DetailTab::AccessPoints => ap_col_count(app),
472 DetailTab::Network => mt_col_count(app),
473 _ => app.efs_column_ids.len(),
474 }
475 } else {
476 app.efs_column_ids.len()
477 }
478}
479
480pub fn next_preferences(app: &mut App) {
481 let page_size_idx = active_prefs_col_count(app) + 2;
482 if app.column_selector_index < page_size_idx {
483 app.column_selector_index = page_size_idx;
484 } else {
485 app.column_selector_index = 0;
486 }
487}
488
489pub fn prev_preferences(app: &mut App) {
490 let page_size_idx = active_prefs_col_count(app) + 2;
491 if app.column_selector_index >= page_size_idx {
492 app.column_selector_index = 0;
493 } else {
494 app.column_selector_index = page_size_idx;
495 }
496}
497
498pub fn column_selector_max(app: &App) -> usize {
499 active_prefs_col_count(app) + 6
500}
501
502pub fn column_count(app: &App) -> usize {
503 active_prefs_col_count(app)
504}