|
1 | 1 | <script lang="ts">
|
2 | 2 | import type { EventSummaryModel, SummaryTemplateKeys } from '$features/events/components/summary/index';
|
3 | 3 |
|
4 |
| - import * as DataTable from '$comp/data-table'; |
| 4 | + import AutomaticRefreshIndicatorButton from '$comp/AutomaticRefreshIndicatorButton.svelte'; |
5 | 5 | import * as FacetedFilter from '$comp/faceted-filter';
|
6 | 6 | import { toFacetedFilters } from '$comp/filters/facets';
|
7 | 7 | import { DateFilter, filterChanged, filterRemoved, FilterSerializer, getDefaultFilters, type IFilter, toFilter } from '$comp/filters/filters.svelte';
|
|
12 | 12 | import { shouldRefreshPersistentEventChanged } from '$features/events/components/filters';
|
13 | 13 | import EventsDataTable from '$features/events/components/table/EventsDataTable.svelte';
|
14 | 14 | import { getTableContext } from '$features/events/components/table/options.svelte';
|
| 15 | + import { isTableEmpty, removeTableData, removeTableSelection } from '$features/shared/table'; |
15 | 16 | import { ChangeType, type WebSocketMessageValue } from '$features/websockets/models';
|
16 | 17 | import { useFetchClientStatus } from '$shared/api/api.svelte';
|
17 | 18 | import { persisted } from '$shared/persisted.svelte';
|
|
26 | 27 | selectedEventId = row.id;
|
27 | 28 | }
|
28 | 29 |
|
29 |
| - let showRefreshStaleDataRow = $state(false); |
30 | 30 | const limit = persisted<number>('events.limit', 10);
|
31 | 31 | const defaultFilters = getDefaultFilters();
|
32 | 32 | const persistedFilters = persisted<IFilter[]>('events.filters', defaultFilters, new FilterSerializer());
|
|
51 | 51 |
|
52 | 52 | const context = getTableContext<EventSummaryModel<SummaryTemplateKeys>>({ limit: limit.value, mode: 'summary' });
|
53 | 53 | const table = createTable(context.options);
|
| 54 | + const canRefresh = $derived(!table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected() && !table.getCanPreviousPage()); |
54 | 55 |
|
55 | 56 | const client = useFetchClient();
|
56 | 57 | const clientStatus = useFetchClientStatus(client);
|
57 |
| -
|
58 |
| - let response = $state<FetchClientResponse<EventSummaryModel<SummaryTemplateKeys>[]>>(); |
| 58 | + let clientResponse = $state<FetchClientResponse<EventSummaryModel<SummaryTemplateKeys>[]>>(); |
59 | 59 |
|
60 | 60 | async function loadData() {
|
61 | 61 | if (client.isLoading) {
|
62 | 62 | return;
|
63 | 63 | }
|
64 | 64 |
|
65 |
| - response = await client.getJSON<EventSummaryModel<SummaryTemplateKeys>[]>('events', { |
| 65 | + clientResponse = await client.getJSON<EventSummaryModel<SummaryTemplateKeys>[]>('events', { |
66 | 66 | params: {
|
67 | 67 | ...context.parameters,
|
68 | 68 | filter,
|
69 | 69 | time
|
70 | 70 | }
|
71 | 71 | });
|
72 | 72 |
|
73 |
| - if (response.ok) { |
74 |
| - context.data = response.data || []; |
75 |
| - context.meta = response.meta; |
76 |
| - table.resetRowSelection(); |
| 73 | + if (clientResponse.ok) { |
| 74 | + context.data = clientResponse.data || []; |
| 75 | + context.meta = clientResponse.meta; |
77 | 76 | }
|
78 | 77 | }
|
79 | 78 | const debouncedLoadData = debounce(10000, loadData);
|
80 | 79 |
|
81 | 80 | async function onPersistentEvent(message: WebSocketMessageValue<'PersistentEventChanged'>) {
|
82 | 81 | if (message.id && message.change_type === ChangeType.Removed) {
|
83 |
| - // Remove the event from the selection if it was selected |
84 |
| - if (table.getIsSomeRowsSelected()) { |
85 |
| - const { rowSelection } = table.getState(); |
86 |
| - if (message.id && rowSelection[message.id]) { |
87 |
| - table.setRowSelection((old) => { |
88 |
| - const filtered = Object.entries(old).filter(([id]) => id !== message.id); |
89 |
| - return Object.fromEntries(filtered); |
90 |
| - }); |
91 |
| - } |
92 |
| - } |
93 |
| -
|
94 |
| - // Remove deleted event from the grid data |
95 |
| - if (table.options.data.find((doc) => doc.id === message.id)) { |
96 |
| - table.options.data = table.options.data.filter((doc) => doc.id !== message.id); |
| 82 | + removeTableSelection(table, message.id); |
97 | 83 |
|
| 84 | + if (removeTableData(table, (doc) => doc.id === message.id)) { |
98 | 85 | // If the grid data is empty from all events being removed, we should refresh the data.
|
99 |
| - if (table.options.data.length === 0) { |
| 86 | + if (isTableEmpty(table)) { |
100 | 87 | await debouncedLoadData();
|
101 | 88 | return;
|
102 | 89 | }
|
|
108 | 95 | return;
|
109 | 96 | }
|
110 | 97 |
|
111 |
| - // Do not refresh if the grid has selections. |
112 |
| - if (table.getIsSomeRowsSelected()) { |
113 |
| - showRefreshStaleDataRow = true; |
114 |
| - return; |
115 |
| - } |
116 |
| -
|
117 |
| - // Do not refresh if the grid is currently paged. |
118 |
| - if (table.getPageCount() > 1) { |
119 |
| - showRefreshStaleDataRow = true; |
| 98 | + // Do not refresh if the grid has selections or grid is currently paged. |
| 99 | + if (canRefresh) { |
120 | 100 | return;
|
121 | 101 | }
|
122 | 102 |
|
123 | 103 | await debouncedLoadData();
|
124 | 104 | }
|
125 | 105 |
|
126 |
| - async function refresh() { |
127 |
| - showRefreshStaleDataRow = false; |
128 |
| - await loadData(); |
129 |
| - } |
130 |
| -
|
131 |
| - useEventListener(document, 'refresh', async () => await loadData()); |
| 106 | + useEventListener(document, 'refresh', () => loadData()); |
132 | 107 | useEventListener(document, 'PersistentEventChanged', async (event) => await onPersistentEvent((event as CustomEvent).detail));
|
133 | 108 |
|
134 | 109 | $effect(() => {
|
|
138 | 113 |
|
139 | 114 | <div class="flex flex-col space-y-4">
|
140 | 115 | <Card.Root>
|
141 |
| - <Card.Title class="p-6 pb-0 text-2xl" level={2}>Events</Card.Title> |
142 |
| - <Card.Content> |
| 116 | + <Card.Title class="gap-x-1 p-6 pb-0 text-2xl" level={2} |
| 117 | + >Events |
| 118 | + <AutomaticRefreshIndicatorButton {canRefresh} refresh={loadData} /></Card.Title |
| 119 | + > |
| 120 | + <Card.Content class="pt-4"> |
143 | 121 | <EventsDataTable bind:limit={limit.value} isLoading={clientStatus.isLoading} rowClick={rowclick} {table}>
|
144 | 122 | {#snippet toolbarChildren()}
|
145 | 123 | <FacetedFilter.Root changed={onFilterChanged} {facets} remove={onFilterRemoved}></FacetedFilter.Root>
|
146 | 124 | {/snippet}
|
147 |
| - {#snippet bodyChildren()} |
148 |
| - {#if showRefreshStaleDataRow} |
149 |
| - <DataTable.DataTableRefresh {table} {refresh} /> |
150 |
| - {/if} |
151 |
| - {/snippet} |
152 | 125 | </EventsDataTable>
|
153 | 126 | </Card.Content>
|
154 | 127 | </Card.Root>
|
|
0 commit comments