diff --git a/ui/src/components/filters/index.tsx b/ui/src/components/filters/index.tsx index b25ea95..fe5e225 100644 --- a/ui/src/components/filters/index.tsx +++ b/ui/src/components/filters/index.tsx @@ -120,6 +120,12 @@ function Filters(props: FiltersProps) { } } + function handleNLogsEnter(e: KeyboardEvent) { + if (e.key === "Enter") { + handleLogsSelectionChanged(gridsRefs); + } + } + function getSimpleSearchHTML(term: SearchTerm, i: Accessor) { return ( <> @@ -207,6 +213,23 @@ function Filters(props: FiltersProps) { label="Errors Only" labelPlacement="start" /> + + + setFilters("firstN", isNaN(+val) || +val < 0 ? 0 : +val) + } + onKeyDown={handleNLogsEnter} + /> + + setFilters("lastN", isNaN(+val) || +val < 0 ? 0 : +val) + } + onKeyDown={handleNLogsEnter} + /> diff --git a/ui/src/components/filters/useViewModel.tsx b/ui/src/components/filters/useViewModel.tsx index bd21f3a..b6bb4fa 100644 --- a/ui/src/components/filters/useViewModel.tsx +++ b/ui/src/components/filters/useViewModel.tsx @@ -30,6 +30,8 @@ interface FiltersData { terms: SearchTerm[]; logs: JSONLogs; errorsOnly: boolean; + firstN: number; + lastN: number; } function defaultFilters(): FiltersData { @@ -46,6 +48,8 @@ function defaultFilters(): FiltersData { ], logs: [], errorsOnly: false, + firstN: 0, + lastN: 0, }; } @@ -102,7 +106,17 @@ function useViewModel(props: FiltersProps) { function populateMap(gridRef: AgGridSolidRef) { for (const r of gridRef.api.getSelectedRows() as GroupedMsg[]) { - r.logs.forEach((l) => map.set(l[LogData.logKeys.id], l)); + let nLogs: JSONLogs = []; + if (filters.firstN) { + nLogs = r.logs.slice(0, filters.firstN); + } + if (filters.lastN) { + nLogs = [...nLogs, ...r.logs.slice(-filters.lastN)]; + } + + if (!nLogs.length) nLogs = r.logs; + + nLogs.forEach((l) => map.set(l[LogData.logKeys.id], l)); } } }