search: index business entities + dataset quick-filters
Build dedicated de-duplicated entity indices (atc-customers ~39k, atc-employees ~39k, atc-products) from Trino so users can search by customer/employee name, id and email directly instead of scanning raw transaction rows. Raise per-table sample caps for the big source tables (sales_orders, employee_events, supplychain events, device_metrics) and all iceberg/Hadoop tables for broader row-level coverage. UI: add Datasets quick-filter chips (Customers, Employees, Products, Sales orders, HR events, Supply chain, Telemetry, Lakehouse) and default the Search tab to business data instead of an infra-looking empty view.
This commit is contained in:
@@ -126,7 +126,7 @@ export function SearchView() {
|
||||
useEffect(() => { load(); loadSourceAgg() }, [load, loadSourceAgg])
|
||||
useEffect(() => { loadIndices() }, [loadIndices])
|
||||
|
||||
const runSearch = useCallback(async (resetFrom = true) => {
|
||||
const runSearch = useCallback(async (resetFrom = true, indicesOverride?: string[]) => {
|
||||
setSearching(true)
|
||||
setSearchError(null)
|
||||
const nextFrom = resetFrom ? 0 : from
|
||||
@@ -137,7 +137,7 @@ export function SearchView() {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
q,
|
||||
indices: [...selected],
|
||||
indices: indicesOverride ?? [...selected],
|
||||
filters,
|
||||
from: nextFrom,
|
||||
size,
|
||||
@@ -166,6 +166,22 @@ export function SearchView() {
|
||||
setFilters((f) => (f.some((x) => x.field === field && x.value === value) ? f : [...f, { field, value }]))
|
||||
}
|
||||
|
||||
const applyPreset = (test: ((n: string) => boolean) | null) => {
|
||||
const names = test ? indices.map((i) => i.name).filter(test) : []
|
||||
setSelected(new Set(names))
|
||||
runSearch(true, names)
|
||||
}
|
||||
|
||||
// show business data immediately instead of an empty/infra-looking view
|
||||
const didInit = useRef(false)
|
||||
useEffect(() => {
|
||||
if (didInit.current || indices.length === 0) return
|
||||
didInit.current = true
|
||||
const cust = indices.find((i) => i.name === 'atc-customers')
|
||||
if (cust) applyPreset((n) => n === 'atc-customers')
|
||||
/* eslint-disable-next-line */
|
||||
}, [indices])
|
||||
|
||||
const toggleIndex = (name: string) => {
|
||||
setSelected((s) => {
|
||||
const n = new Set(s)
|
||||
@@ -328,6 +344,36 @@ export function SearchView() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* dataset quick filters */}
|
||||
<div className="flex shrink-0 flex-wrap items-center gap-1.5 border-b border-border px-3 pt-3 text-[10px]">
|
||||
<span className="mr-1 font-semibold uppercase tracking-wider text-foreground-faint">Datasets</span>
|
||||
{[
|
||||
{ label: 'All data', test: null as ((n: string) => boolean) | null },
|
||||
{ label: 'Customers', test: (n: string) => n === 'atc-customers' },
|
||||
{ label: 'Employees', test: (n: string) => n === 'atc-employees' },
|
||||
{ label: 'Products', test: (n: string) => n === 'atc-products' },
|
||||
{ label: 'Sales orders', test: (n: string) => n.includes('sales-orders') && !n.includes('masked') },
|
||||
{ label: 'HR events', test: (n: string) => n.includes('employee-events') },
|
||||
{ label: 'Supply chain', test: (n: string) => n.includes('supplychain') },
|
||||
{ label: 'Telemetry', test: (n: string) => n.includes('device-metrics') },
|
||||
{ label: 'Lakehouse (Hadoop)', test: (n: string) => n.startsWith('atc-iceberg') },
|
||||
].map((p) => {
|
||||
const names = p.test ? indices.map((i) => i.name).filter(p.test) : []
|
||||
const active = p.test ? names.length > 0 && names.every((n) => selected.has(n)) && selected.size === names.length : selected.size === 0
|
||||
if (p.test && names.length === 0) return null
|
||||
return (
|
||||
<button
|
||||
key={p.label}
|
||||
type="button"
|
||||
onClick={() => applyPreset(p.test)}
|
||||
className={cn('rounded-full border px-2.5 py-1 font-medium transition-colors', active ? 'border-docker bg-docker/15 text-docker' : 'border-border text-foreground-muted hover:bg-surface-overlay')}
|
||||
>
|
||||
{p.label}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* search bar */}
|
||||
<div className="shrink-0 space-y-2 border-b border-border p-3">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
|
||||
Reference in New Issue
Block a user