Skip to content

Commit 99b6737

Browse files
committed
Fixed grid filtering
1 parent fbf716e commit 99b6737

File tree

8 files changed

+300
-336
lines changed

8 files changed

+300
-336
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { getKeywordFilter, getOrganizationFilter, getProjectFilter, getStackFilter, type IFilter } from '$comp/filters/filters.svelte';
2+
3+
export function shouldRefreshPersistentEventChanged(
4+
filters: IFilter[],
5+
filter: string,
6+
organization_id?: string,
7+
project_id?: string,
8+
stack_id?: string,
9+
id?: string
10+
) {
11+
if (!filter) {
12+
return true;
13+
}
14+
15+
if (id) {
16+
// This could match any kind of lucene query (even must not filtering)
17+
const keywordFilter = getKeywordFilter(filters);
18+
if (keywordFilter && !keywordFilter.isEmpty()) {
19+
if (keywordFilter.value!.includes(id)) {
20+
return true;
21+
}
22+
}
23+
}
24+
25+
if (stack_id) {
26+
const stackFilter = getStackFilter(filters);
27+
if (stackFilter && !stackFilter.isEmpty()) {
28+
return stackFilter.value === stack_id;
29+
}
30+
}
31+
32+
if (project_id) {
33+
const projectFilter = getProjectFilter(filters);
34+
if (projectFilter && !projectFilter.isEmpty()) {
35+
return projectFilter.value.includes(project_id);
36+
}
37+
}
38+
39+
if (organization_id) {
40+
const organizationFilter = getOrganizationFilter(filters);
41+
if (organizationFilter && !organizationFilter.isEmpty()) {
42+
return organizationFilter.value === organization_id;
43+
}
44+
}
45+
46+
return true;
47+
}

src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte

Lines changed: 4 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -2,137 +2,18 @@
22
import type { Snippet } from 'svelte';
33
44
import * as DataTable from '$comp/data-table';
5-
import { getKeywordFilter, getOrganizationFilter, getProjectFilter, getStackFilter, type IFilter } from "$comp/filters/filters.svelte";
6-
import { ChangeType, type WebSocketMessageValue } from '$features/websockets/models';
7-
import { DEFAULT_LIMIT } from '$shared/api';
8-
import { type FetchClientResponse, useFetchClient } from '@exceptionless/fetchclient';
9-
import { createTable } from '@tanstack/svelte-table';
10-
import { useEventListener } from 'runed';
11-
import { debounce } from 'throttle-debounce';
5+
import { type Table } from '@tanstack/svelte-table';
126
13-
import type { GetEventsMode } from '../../api.svelte';
147
import type { EventSummaryModel, SummaryTemplateKeys } from '../summary/index';
158
16-
import { getTableContext } from './options.svelte';
17-
189
interface Props {
19-
filter: string;
20-
filters: IFilter[];
2110
limit: number;
22-
mode?: GetEventsMode;
23-
pageFilter?: string;
2411
rowclick?: (row: EventSummaryModel<SummaryTemplateKeys>) => void;
25-
time: string;
12+
table: Table<EventSummaryModel<SummaryTemplateKeys>>;
2613
toolbarChildren?: Snippet;
2714
}
2815
29-
let { filter, filters, limit = $bindable(DEFAULT_LIMIT), mode = 'summary', pageFilter = undefined, rowclick, time, toolbarChildren }: Props = $props();
30-
const context = getTableContext<EventSummaryModel<SummaryTemplateKeys>>({ limit, mode });
31-
const table = createTable(context.options);
32-
33-
const client = useFetchClient();
34-
let response: FetchClientResponse<EventSummaryModel<SummaryTemplateKeys>[]>;
35-
36-
$effect(() => {
37-
limit = Number(context.limit);
38-
loadData();
39-
});
40-
41-
async function loadData() {
42-
if (client.loading) {
43-
return;
44-
}
45-
46-
response = await client.getJSON<EventSummaryModel<SummaryTemplateKeys>[]>('events', {
47-
params: {
48-
...context.parameters,
49-
filter: [pageFilter, filter].filter(Boolean).join(' '),
50-
time
51-
}
52-
});
53-
54-
if (response.ok) {
55-
context.data = response.data || [];
56-
context.meta = response.meta;
57-
table.resetRowSelection();
58-
}
59-
}
60-
const debouncedLoadData = debounce(10000, loadData);
61-
62-
async function onPersistentEvent(message: WebSocketMessageValue<'PersistentEventChanged'>) {
63-
const shouldRefresh = () => {
64-
if (!filter) {
65-
return true;
66-
}
67-
68-
const { id, organization_id, project_id, stack_id } = message;
69-
if (id) {
70-
// Check to see if any records on the page match
71-
if (mode === "summary" && table.options.data.some((doc) => doc.id === id)) {
72-
return true;
73-
}
74-
75-
// This could match any kind of lucene query (even must not filtering)
76-
const keywordFilter = getKeywordFilter(filters);
77-
if (keywordFilter && !keywordFilter.isEmpty()) {
78-
if (keywordFilter.value!.includes(id)) {
79-
return true;
80-
}
81-
}
82-
}
83-
84-
if (stack_id) {
85-
// Check to see if any records on the page match
86-
if (mode !== "summary" && table.options.data.some((doc) => doc.id === stack_id)) {
87-
return true;
88-
}
89-
90-
const stackFilter = getStackFilter(filters);
91-
if (stackFilter && !stackFilter.isEmpty()) {
92-
return stackFilter.value === stack_id;
93-
}
94-
}
95-
96-
if (project_id) {
97-
const projectFilter = getProjectFilter(filters);
98-
if (projectFilter && !projectFilter.isEmpty()) {
99-
return projectFilter.value.includes(project_id);
100-
}
101-
}
102-
103-
if (organization_id) {
104-
const organizationFilter = getOrganizationFilter(filters);
105-
if (organizationFilter && !organizationFilter.isEmpty()) {
106-
return organizationFilter.value === organization_id;
107-
}
108-
}
109-
110-
return true;
111-
};
112-
113-
switch (message.change_type) {
114-
case ChangeType.Added:
115-
case ChangeType.Saved:
116-
if (shouldRefresh()) {
117-
await debouncedLoadData();
118-
}
119-
120-
break;
121-
case ChangeType.Removed:
122-
if (shouldRefresh()) {
123-
if (message.id && mode === "summary") {
124-
table.options.data = table.options.data.filter((doc) => doc.id !== message.id);
125-
}
126-
127-
await debouncedLoadData();
128-
}
129-
130-
break;
131-
}
132-
}
133-
134-
useEventListener(document, 'refresh', async () => await loadData());
135-
useEventListener(document, 'PersistentEventChanged', async (event) => await onPersistentEvent((event as CustomEvent).detail));
16+
let { limit = $bindable(), rowclick, table, toolbarChildren }: Props = $props();
13617
</script>
13718

13819
<DataTable.Root>
@@ -143,6 +24,6 @@
14324
</DataTable.Toolbar>
14425
<DataTable.Body {rowclick} {table}></DataTable.Body>
14526
<DataTable.Pagination {table}>
146-
<DataTable.PageSize bind:value={context.limit} {table}></DataTable.PageSize>
27+
<DataTable.PageSize bind:value={limit} {table}></DataTable.PageSize>
14728
</DataTable.Pagination>
14829
</DataTable.Root>

src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsTailLogDataTable.svelte

Lines changed: 0 additions & 167 deletions
This file was deleted.

0 commit comments

Comments
 (0)