# Filtering, Search & Column Management

# Filtering, Search & Column Management

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [.devin/rules/always-check-rules-first.md](.devin/rules/always-check-rules-first.md)
- [src/lib/components/entity-list-table/composables/useClientSelection.svelte.ts](src/lib/components/entity-list-table/composables/useClientSelection.svelte.ts)
- [src/lib/components/entity-list-table/composables/useDeletionFilter.svelte.ts](src/lib/components/entity-list-table/composables/useDeletionFilter.svelte.ts)
- [src/lib/components/entity-list-table/composables/useFilterPersistence.svelte.ts](src/lib/components/entity-list-table/composables/useFilterPersistence.svelte.ts)
- [src/lib/components/entity-list-table/composables/useFilters.svelte.ts](src/lib/components/entity-list-table/composables/useFilters.svelte.ts)
- [src/lib/components/entity-list-table/composables/useKeyboardNavigation.svelte.ts](src/lib/components/entity-list-table/composables/useKeyboardNavigation.svelte.ts)
- [src/lib/components/entity-list-table/composables/usePreviewPanel.svelte.ts](src/lib/components/entity-list-table/composables/usePreviewPanel.svelte.ts)
- [src/lib/components/entity-list-table/composables/useScrollPreservation.svelte.ts](src/lib/components/entity-list-table/composables/useScrollPreservation.svelte.ts)
- [src/lib/components/entity-list-table/composables/useStickyColumns.svelte.ts](src/lib/components/entity-list-table/composables/useStickyColumns.svelte.ts)
- [src/lib/components/entity-list-table/pagination/Pagination.svelte](src/lib/components/entity-list-table/pagination/Pagination.svelte)
- [src/lib/components/entity-list-table/panels/ColumnSelectorPanel.svelte](src/lib/components/entity-list-table/panels/ColumnSelectorPanel.svelte)
- [src/lib/components/entity-list-table/panels/FiltersPanel.svelte](src/lib/components/entity-list-table/panels/FiltersPanel.svelte)
- [src/lib/components/entity-list-table/panels/SearchInPanel.svelte](src/lib/components/entity-list-table/panels/SearchInPanel.svelte)
- [src/lib/components/entity-list-table/search/SearchSyntaxHighlighter.svelte](src/lib/components/entity-list-table/search/SearchSyntaxHighlighter.svelte)
- [src/lib/components/entity-list-table/search/search-syntax.ts](src/lib/components/entity-list-table/search/search-syntax.ts)
- [src/lib/components/entity-list-table/toolbar/BulkActions.svelte](src/lib/components/entity-list-table/toolbar/BulkActions.svelte)
- [src/lib/components/entity-list-table/toolbar/DeletionFilterToggle.svelte](src/lib/components/entity-list-table/toolbar/DeletionFilterToggle.svelte)
- [src/lib/components/entity-list-table/toolbar/SearchBar.svelte](src/lib/components/entity-list-table/toolbar/SearchBar.svelte)
- [src/lib/components/ui/input-group/highlighted-input.svelte](src/lib/components/ui/input-group/highlighted-input.svelte)
- [src/lib/components/ui/input-group/index.ts](src/lib/components/ui/input-group/index.ts)
- [src/lib/entity-list/sheets/panels/FiltersPanel.svelte](src/lib/entity-list/sheets/panels/FiltersPanel.svelte)
- [src/lib/entity-list/types.ts](src/lib/entity-list/types.ts)
- [src/lib/i18n/date-format.ts](src/lib/i18n/date-format.ts)
- [src/routes/(app)/customers/+page.svelte](src/routes/(app)/customers/+page.svelte)

</details>



The Primebrick frontend provides a robust system for data manipulation within the `EntityListTable`. This system encompasses standard and advanced filtering, high-performance search with syntax highlighting, and dynamic column management via drag-and-drop.

## Filtering System

The filtering logic is primarily managed by the `FiltersPanel.svelte` component and the `useFilters` and `useAdvancedFilters` composables.

### FiltersPanel
The `FiltersPanel` provides a dual-mode interface for narrowing down entity records [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:1-59]().

1.  **Standard Filters**: Provides direct inputs for columns marked as `filterable` in the entity metadata [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:52]().
2.  **Advanced Filters**: Allows users to build complex queries using specific operators (e.g., `contains`, `BETWEEN`, `!=`) and join them with a global `AND` or `OR` connector [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:75-76]().

### Operator Mapping
Available operators are determined by the column's data type via `getOperatorsForColumnType` [src/lib/entity-list/types.ts:157-170]():

| Column Type | Supported Operators |
| :--- | :--- |
| `text` | `=`, `!=`, `contains`, `startsWith`, `endsWith` |
| `badge` | `=`, `!=` |
| `date` / `datetime` | `=`, `!=`, `>`, `<`, `>=`, `<=`, `BETWEEN` |
| Default (Numeric) | `=`, `!=`, `>`, `<`, `>=`, `<=` |

### Date Normalization & IANA Timezones
When filtering by `date` or `datetime`, the system uses `DateWheelPicker` [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:30](). 
- **Normalization**: Values are converted to UTC ISO strings before being sent to the backend [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:142-145]().
- **IANA Handling**: If a column has `datetimeIanaToggle` enabled, the panel can include the specific record-level IANA timezone in the filter payload if it differs from the browser's timezone [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:151-156]().

**Data Flow: Filter Application**
```mermaid
graph TD
    subgraph "UI Layer"
        FP["FiltersPanel.svelte"]
        DWP["DateWheelPicker.svelte"]
    end

    subgraph "Logic Layer"
        UF["useFilters.ts"]
        UAF["useAdvancedFilters.ts"]
        UP["useFilterPersistence.ts"]
    end

    FP -->|"onFilterValuesChange"| UF
    FP -->|"onAdvancedFiltersChange"| UAF
    UF -->|"writeFilterValues"| UP
    UP -->|"sessionStorage"| DB[(Browser Storage)]
    UF -->|"Trigger Re-fetch"| API["/api/v1/entities/..."]
```
Sources: [src/lib/entity-list/sheets/panels/FiltersPanel.svelte:132-165](), [src/lib/entity-list/types.ts:157-170](), [src/lib/components/entity-list-table/composables/useFilters.svelte.ts:16-47](), [src/lib/components/entity-list-table/composables/useFilterPersistence.svelte.ts:31-39]().

---

## Search & Syntax Highlighting

The search infrastructure consists of a `SearchBar` component that supports both simple text search and targeted field searching.

### SearchBar & HighlightedInput
The search input uses a layered approach in `highlighted-input.svelte` to provide syntax highlighting while maintaining native input behavior:
- **Underlay**: A `div` containing `SearchSyntaxHighlighter` that renders colored tokens [src/lib/components/ui/input-group/highlighted-input.svelte:27-48]().
- **Overlay**: A transparent native `input` that captures user keystrokes and handles the caret [src/lib/components/ui/input-group/highlighted-input.svelte:51-65]().
- **Sync**: The `syncScroll` function ensures the underlay tokens align perfectly with the (invisible) text in the input [src/lib/components/ui/input-group/highlighted-input.svelte:18-22]().

### Search Syntax
The `search-syntax.ts` utility (referenced by `SearchSyntaxHighlighter`) parses the search string for specific tokens:
- **Wildcards**: Symbols like `*` or `%` are highlighted to indicate pattern matching.
- **Field Directives**: Syntax like `name:John` (if implemented in the highlighter) allows targeting specific columns.

### SearchInPanel
The `SearchInPanel` allows users to restrict the search to specific columns. This selection is persisted in `sessionStorage` via keys like `pb:customers:list:searchInKeys` [src/routes/(app)/customers/+page.svelte:99-109]().

Sources: [src/lib/components/ui/input-group/highlighted-input.svelte:6-23](), [src/routes/(app)/customers/+page.svelte:99-109]().

---

## Column Management

Column visibility and ordering are managed through the `ColumnsPanel` (often referred to as `ColumnSelectorPanel`).

### Drag-and-Drop Reordering
The system utilizes the `Sortable` component to allow users to reorder columns.
- **Implementation**: Columns are grouped into `sticky`, `data`, and `auditing` categories [src/lib/entity-list/types.ts:78-84]().
- **Persistence**: The resulting order is saved to `sessionStorage` [src/routes/(app)/customers/+page.svelte:110]().

### Sticky Columns
Sticky columns (pinned to the left) are handled by the `useStickyColumns` composable. It calculates horizontal offsets dynamically using a `ResizeObserver` to ensure they remain pinned during horizontal scrolling [src/lib/components/entity-list-table/composables/useStickyColumns.svelte.ts:54-91]().

**Entity List Configuration Mapping**
```mermaid
classDiagram
    class MetaColumn {
        +string key
        +string type
        +boolean sortable
        +boolean searchable
        +boolean filterable
    }
    class EntityListListMeta {
        +MetaColumn[] columns
        +MetaColumn[] stickyColumns
        +MetaColumn[] auditingColumns
        +ViewVisibilityConfig viewVisibility
    }
    class DeletionFilterMode {
        <<enumeration>>
        non_deleted
        deleted
        all
    }
    EntityListListMeta "1" -- "*" MetaColumn : contains
```
Sources: [src/lib/entity-list/types.ts:21-75](), [src/lib/components/entity-list-table/composables/useStickyColumns.svelte.ts:4-50]().

---

## Persistence & State Management

Filter and column states are preserved across page reloads using `sessionStorage`.

### useFilterPersistence
This composable provides standardized methods for reading and writing filter states:
- `readFilterValues()` / `writeFilterValues()`: For standard filters [src/lib/components/entity-list-table/composables/useFilterPersistence.svelte.ts:17-39]().
- `readAdvancedFilters()` / `writeAdvancedFilters()`: For the advanced filter array [src/lib/components/entity-list-table/composables/useFilterPersistence.svelte.ts:41-63]().

### DeletionFilterToggle
The `useDeletionFilter` composable manages the `deletionFilterMode` state (`non_deleted`, `deleted`, or `all`).
- **Sync**: It automatically writes changes to storage and notifies the parent component to trigger a data refresh [src/lib/components/entity-list-table/composables/useDeletionFilter.svelte.ts:59-68]().

### FilterBar
The `FilterBar` (rendered above the table) displays active filters as removable badges. Clicking the "X" on a badge calls `clearFilter(key)` in the `useFilters` composable, which updates the state and triggers a server-side reload [src/lib/components/entity-list-table/composables/useFilters.svelte.ts:26-31]().

Sources: [src/lib/components/entity-list-table/composables/useFilterPersistence.svelte.ts:1-74](), [src/lib/components/entity-list-table/composables/useDeletionFilter.svelte.ts:1-74](), [src/lib/components/entity-list-table/composables/useFilters.svelte.ts:26-31]().

---
