Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { EventSummaryModel, StackSummaryModel, SummaryTemplateKeys } from '$features/events/components/summary';

import { describe, expect, it } from 'vitest';

import { getColumns } from './options.svelte';

describe('getColumns', () => {
it('uses dedicated stack-mode controls instead of API sort parameters', () => {
const result = getColumns<StackSummaryModel<SummaryTemplateKeys>>('stack_frequent');
const columnsById = Object.fromEntries(result.map((column) => [column.id, column]));

expect(columnsById.events?.enableSorting).toBe(false);
expect(columnsById.first?.enableSorting).toBe(false);
expect(columnsById.last?.enableSorting).toBe(false);
expect(columnsById.events?.header).toBeTypeOf('function');
expect(columnsById.first?.header).toBeTypeOf('function');
expect(columnsById.last?.header).toBeTypeOf('function');
});

it('keeps summary message column unsortable', () => {
const result = getColumns<EventSummaryModel<SummaryTemplateKeys>>('summary');
const columnsById = Object.fromEntries(result.map((column) => [column.id, column]));

expect(columnsById.message?.enableSorting).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { EventSummaryModel, StackSummaryModel, SummaryModel, SummaryTemplat
import LogLevel from '../log-level.svelte';
import Summary from '../summary/summary.svelte';
import EventsUserIdentitySummaryCell from './events-user-identity-summary-cell.svelte';
import StackSortHeader from './stack-sort-header.svelte';
import StackStatusCell from './stack-status-cell.svelte';
import StackUsersSummaryCell from './stack-users-summary-cell.svelte';

Expand All @@ -25,9 +26,11 @@ export const defaultEventColumnVisibility: ColumnVisibilityState = {
version: false
};

export type StackSortMode = Extract<GetEventsMode, 'stack_frequent' | 'stack_new' | 'stack_recent'>;

export function getColumns<TSummaryModel extends SummaryModel<SummaryTemplateKeys>>(
mode: GetEventsMode = 'summary',
options?: { showType?: boolean }
options?: { onStackSort?: (mode: StackSortMode) => void; showType?: boolean }
): ColumnDef<StockFeatures, TSummaryModel, unknown>[] {
const showType = options?.showType ?? true;
const columns: ColumnDef<StockFeatures, TSummaryModel, unknown>[] = [
Expand Down Expand Up @@ -176,7 +179,12 @@ export function getColumns<TSummaryModel extends SummaryModel<SummaryTemplateKey
accessorKey: nameof<StackSummaryModel<SummaryTemplateKeys>>('total'),
cell: (prop) => renderComponent(NumberFormatter, { value: prop.getValue<number>() }),
enableSorting: false,
header: 'Events',
header: () =>
renderComponent(StackSortHeader, {
active: mode === 'stack_frequent',
label: 'Events',
onclick: () => options?.onStackSort?.('stack_frequent')
}),
id: 'events',
meta: {
class: 'w-24'
Expand All @@ -186,7 +194,12 @@ export function getColumns<TSummaryModel extends SummaryModel<SummaryTemplateKey
accessorKey: nameof<StackSummaryModel<SummaryTemplateKeys>>('first_occurrence'),
cell: (prop) => renderComponent(TimeAgo, { value: prop.getValue<string>() }),
enableSorting: false,
header: 'First',
header: () =>
renderComponent(StackSortHeader, {
active: mode === 'stack_new',
label: 'First',
onclick: () => options?.onStackSort?.('stack_new')
Comment thread
niemyjski marked this conversation as resolved.
Outdated
}),
id: 'first',
meta: {
class: 'w-36'
Expand All @@ -196,7 +209,12 @@ export function getColumns<TSummaryModel extends SummaryModel<SummaryTemplateKey
accessorKey: nameof<StackSummaryModel<SummaryTemplateKeys>>('last_occurrence'),
cell: (prop) => renderComponent(TimeAgo, { value: prop.getValue<string>() }),
enableSorting: false,
header: 'Last',
header: () =>
renderComponent(StackSortHeader, {
active: mode === 'stack_recent',
label: 'Last',
onclick: () => options?.onStackSort?.('stack_recent')
}),
id: 'last',
meta: {
class: 'w-36'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { Button } from '$comp/ui/button';
import ArrowDown from '@lucide/svelte/icons/arrow-down';

interface Props {
active: boolean;
label: string;
onclick: () => void;
}

let { active, label, onclick }: Props = $props();
</script>

<Button aria-label={`Sort by ${label} descending`} aria-pressed={active} class="h-8" {onclick} variant="ghost">
{label}
{#if active}
<ArrowDown aria-hidden="true" />
{/if}
</Button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { fireEvent, render, screen } from '@testing-library/svelte';
import { describe, expect, it, vi } from 'vitest';

import StackSortHeader from './stack-sort-header.svelte';

describe('StackSortHeader', () => {
it('exposes the active descending sort and handles selection', async () => {
const onclick = vi.fn();
render(StackSortHeader, { active: true, label: 'Events', onclick });

const button = screen.getByRole('button', { name: 'Sort by Events descending' });
expect(button).toHaveAttribute('aria-pressed', 'true');

await fireEvent.click(button);

expect(onclick).toHaveBeenCalledOnce();
});

it('does not mark inactive sort modes as selected', () => {
render(StackSortHeader, { active: false, label: 'First', onclick: vi.fn() });

expect(screen.getByRole('button', { name: 'Sort by First descending' })).toHaveAttribute('aria-pressed', 'false');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,10 @@
columnPersistenceKey: 'stacks-column-visibility',
get columns() {
return getColumns<EventSummaryModel<SummaryTemplateKeys>>(eventsQueryParameters.mode, {
onStackSort: (mode) => {
eventsQueryParameters.mode = mode;
table.setPageIndex(0);
},
showType: !hasSingleTypeFilter(eventsQueryParameters.filter)
});
},
Expand Down
Loading