warehouse fixes (#29212)

* fix clicking on sidebar item opening it

* update filters after curl is used

* fix refresh not using latest date

* add fallback when result is empty

* fix not showing latest results when pressing refresh

* cleanup

* Update apps/studio/components/interfaces/DataWarehouse/WarehouseCollectionDetail.tsx

Co-authored-by: Charis <26616127+charislam@users.noreply.github.com>

* simplify copy, comment out search temporarily

---------

Co-authored-by: Charis <26616127+charislam@users.noreply.github.com>
This commit is contained in:
Jordi EnricandCharis authored and GitHub committed 2024-09-12 13:48:43 +02:00
1 parent 93053bbb07
commit 2ab2f0e26b
5 files changed
+63 -57

No files matched your search

@@ -20,28 +20,27 @@ import { DatetimeHelper } from '../Settings/Logs/Logs.types'
import dayjs from 'dayjs'
import { useKeyboardShortcuts } from 'components/grid/components/common/Hooks'
const djs = dayjs()
const INTERVALS: DatetimeHelper[] = [
{
text: 'Last hour',
calcFrom: () => djs.subtract(1, 'hour').toISOString(),
calcTo: () => djs.toISOString(),
calcFrom: () => dayjs().subtract(1, 'hour').toISOString(),
calcTo: () => dayjs().toISOString(),
default: true,
},
{
text: 'Last 12 hours',
calcFrom: () => djs.subtract(12, 'hour').toISOString(),
calcTo: () => djs.toISOString(),
calcFrom: () => dayjs().subtract(12, 'hour').toISOString(),
calcTo: () => dayjs().toISOString(),
},
{
text: 'Last day',
calcFrom: () => djs.subtract(1, 'day').toISOString(),
calcTo: () => djs.toISOString(),
calcFrom: () => dayjs().subtract(1, 'day').toISOString(),
calcTo: () => dayjs().toISOString(),
},
{
text: 'Last 7 days',
calcFrom: () => djs.subtract(7, 'day').toISOString(),
calcTo: () => djs.toISOString(),
calcFrom: () => dayjs().subtract(7, 'day').toISOString(),
calcTo: () => dayjs().toISOString(),
},
]
@@ -57,51 +56,43 @@ export const WarehouseCollectionDetail = () => {
{ projectRef },
{ enabled: hasWarehouse }
)
const collection = (collections || []).find((c) => c.token === collectionToken)
const [params, setParams] = useState({
sql: ``,
})
const collection = collections?.find((c) => c.token === collectionToken)
const [search, setSearch] = useState('')
const [filters, setFilters] = useState({
limit: 100,
offset: 0,
search: '',
interval: {
to: INTERVALS[0].calcTo(),
from: INTERVALS[0].calcFrom(),
to: INTERVALS[0].calcTo,
from: INTERVALS[0].calcFrom,
},
})
const [sql, setSQL] = useState('')
useEffect(() => {
if (collection) {
const from = filters.interval?.from
const to = filters.interval?.to
const from = filters.interval.from()
const to = filters.interval.to()
const sql = `select id, timestamp, event_message from \`${collection.name}\`
const sql = `select id, timestamp from \`${collection.name}\`
where timestamp >= TIMESTAMP('${from}')
${to ? `and timestamp <= TIMESTAMP('${to}')` : ''}
and event_message like '%${filters.search}%'
and timestamp <= TIMESTAMP('${to}')
order by timestamp desc limit ${filters.limit} offset ${filters.offset}
`
setParams((prevParams) => ({
...prevParams,
sql,
}))
setSQL(sql)
}
}, [collection, filters])
}, [filters.interval, filters.limit, filters.offset, collection])
const {
isLoading: queryLoading,
data: queryData,
refetch,
isError,
isRefetching,
} = useWarehouseQueryQuery(
{ ref: projectRef, sql: params.sql },
{ ref: projectRef, sql },
{
enabled: !!params.sql && hasWarehouse,
enabled: !!sql && hasWarehouse,
}
)
@@ -128,14 +119,20 @@ order by timestamp desc limit ${filters.limit} offset ${filters.offset}
const isLoading = queryLoading || collectionsLoading || isRefetching
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
setFilters({ ...filters, search })
refetch()
function refreshResults(e?: React.FormEvent<HTMLFormElement>) {
e?.preventDefault()
setFilters({
...filters,
search,
interval: {
to: () => dayjs().toISOString(),
from: () => filters.interval.from() || dayjs().subtract(1, 'hour').toISOString(),
},
})
}
const queryUrl = `/project/${projectRef}/logs/explorer?q=${encodeURIComponent(
params.sql || ''
sql || ''
)}&source=warehouse`
useKeyboardShortcuts(
@@ -163,7 +160,7 @@ order by timestamp desc limit ${filters.limit} offset ${filters.offset}
<LoadingOpacity active={isLoading}>
<div className="flex flex-col w-full">
<div className="flex justify-between items-center h-12 px-5">
<form onSubmit={handleSubmit} className="flex items-center gap-2">
<form onSubmit={refreshResults} className="flex items-center gap-2">
<h2 className="text-foreground-light max-w-60 truncate" title={collection?.name}>
{collection?.name}
</h2>
@@ -183,7 +180,7 @@ order by timestamp desc limit ${filters.limit} offset ${filters.offset}
Refresh <KeyboardShortcut>R</KeyboardShortcut>
</TooltipContent>
</Tooltip>
<Input
{/* <Input
type="search"
id="search-input"
className="w-52"
@@ -191,17 +188,17 @@ order by timestamp desc limit ${filters.limit} offset ${filters.offset}
placeholder="Search by event message"
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
/> */}
<DatePickers
to={filters.interval?.to}
from={filters.interval?.from}
to={filters.interval?.to()}
from={filters.interval?.from()}
helpers={INTERVALS}
onChange={(e) =>
setFilters({
...filters,
interval: {
to: e.to || '',
from: e.from || '',
to: () => e.to || '',
from: () => e.from || '',
},
})
}
@@ -231,7 +228,7 @@ order by timestamp desc limit ${filters.limit} offset ${filters.offset}
open={testDialogOpen}
onOpenChange={setTestDialogOpen}
onSubmit={() => {
refetch()
refreshResults()
setTestDialogOpen(false)
}}
/>
@@ -252,22 +249,26 @@ order by timestamp desc limit ${filters.limit} offset ${filters.offset}
projectRef={projectRef}
isLoading={isLoading}
data={results}
params={params}
params={{ sql }}
maxHeight="calc(100vh - 139px)"
showHeader={false}
emptyState={
<ProductEmptyState
title="No events found"
size="large"
ctaButtonLabel="Send test event"
onClickCta={() => setTestDialogOpen(true)}
>
<>
<p>
No events match your current search criteria. <br />
Try adjusting your filters or send a test event to populate this collection.
</p>
</>
<ProductEmptyState title="No events found" size="large">
<div className="space-y-4">
<p>Try adjusting your filters, send a test event or refresh the results.</p>
<div className="flex items-center gap-2">
<Button
onClick={() => {
setTestDialogOpen(true)
}}
>
Send test event
</Button>
<Button type="outline" onClick={() => refreshResults()}>
Refresh
</Button>
</div>
</div>
</ProductEmptyState>
}
/>
@@ -99,6 +99,9 @@ export const WarehouseMenuItem = ({ item }: Props) => {
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
onClick={(e) => {
e.preventDefault()
}}
loading={isLoading}
type="text"
className="px-1 opacity-50 hover:opacity-100 !bg-transparent"
@@ -92,7 +92,7 @@ const LogSelection = ({
switch (queryType) {
case 'warehouse':
if (!warehouseQueryData) return null
return <DefaultPreviewSelectionRenderer log={warehouseQueryData.result[0]} />
return <DefaultPreviewSelectionRenderer log={warehouseQueryData.result?.[0] || {}} />
case 'api':
if (!fullLog) return null
if (!fullLog.metadata) return <DefaultPreviewSelectionRenderer log={fullLog} />
@@ -148,7 +148,7 @@ const LogSelection = ({
const rawLog = useMemo(() => {
if (queryType === 'warehouse') {
return warehouseQueryData?.result[0]
return warehouseQueryData?.result?.[0] || {}
}
return fullLog || partialLog
}, [queryType, warehouseQueryData, fullLog, partialLog])
@@ -103,6 +103,7 @@ const LogsLayout = ({ title, children }: PropsWithChildren<LogsLayoutProps>) =>
{collectionQueryEnabled && collectionsLoading ? (
<GenericSkeletonLoader />
) : (
collections?.length &&
collections?.map((item) => (
<WarehouseMenuItem item={item} key={item.id + '-collection-item'} />
))
@@ -201,6 +201,7 @@ export const CodeBlock = ({
e.preventDefault()
return false
}}
suppressContentEditableWarning={true}
>
{codeValue}
</SyntaxHighlighter>