mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 18:05:11 +03:00
chore: added animation polish. added new filter options.
This commit is contained in:
1 parent
9359760711
commit
114cbc1ccd
10 files changed
+164
-75
No files matched your search
@@ -16,7 +16,6 @@ const LogEventChart: React.FC<Props> = ({ data, onBarClick }) => {
|
||||
|
||||
return (
|
||||
<BarChart
|
||||
className="py-1 px-2"
|
||||
minimalHeader
|
||||
minmalChart
|
||||
data={aggregated}
|
||||
@@ -29,7 +28,7 @@ const LogEventChart: React.FC<Props> = ({ data, onBarClick }) => {
|
||||
}}
|
||||
customDateFormat="MMM D, HH:mm"
|
||||
displayDateInUtc
|
||||
noDataMessage={""}
|
||||
noDataMessage={''}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import FunctionInvocationSelectionRender, {
|
||||
import FunctionLogsSelectionRender from './LogSelectionRenderers/FunctionLogsSelectionRender'
|
||||
|
||||
interface Props {
|
||||
log: LogData
|
||||
log: LogData | undefined
|
||||
onClose: () => void
|
||||
queryType?: QueryType
|
||||
}
|
||||
@@ -57,51 +57,79 @@ const LogSelection: FC<Props> = ({ log, onClose, queryType }) => {
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
'h-full flex flex-col flex-grow border border-l',
|
||||
'relative h-full flex flex-col flex-grow border border-l',
|
||||
'border-panel-border-light dark:border-panel-border-dark',
|
||||
'bg-gray-200',
|
||||
].join(' ')}
|
||||
>
|
||||
{log ? (
|
||||
<>
|
||||
<div
|
||||
className={[
|
||||
'bg-panel-header-light dark:bg-panel-header-dark',
|
||||
'border-b border-panel-border-interior-light',
|
||||
'dark:border-panel-border-interior-dark',
|
||||
].join(' ')}
|
||||
>
|
||||
<div className="px-6 py-4 flex items-center">
|
||||
<div className="flex flex-row justify-between items-center w-full">
|
||||
<h3 className="text-xl font-semibold">{header()}</h3>
|
||||
<div className="cursor-pointer" onClick={onClose}>
|
||||
<IconX size={14} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
`transition-all
|
||||
bg-scale-200 absolute w-full h-full text-center flex-col gap-2 flex items-center justify-center ` +
|
||||
(log ? 'opacity-0 z-0' : 'opacity-100 z-10')
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
`transition-all
|
||||
duration-500
|
||||
delay-200
|
||||
w-full
|
||||
flex
|
||||
flex-col
|
||||
justify-center
|
||||
items-center
|
||||
gap-6
|
||||
max-w-sm
|
||||
text-center ` + (log ? 'mt-0 opacity-0 scale-95' : 'mt-8 opacity-100 scale-100')
|
||||
}
|
||||
>
|
||||
<div className="relative border border-scale-600 dark:border-scale-400 w-32 h-4 rounded px-2 flex items-center">
|
||||
<div className="h-0.5 rounded-full w-2/3 bg-scale-600 dark:bg-scale-500"></div>
|
||||
<div className="absolute right-1 -bottom-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="1"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="
|
||||
flex-grow overflow-y-auto
|
||||
bg-panel-body-light dark:bg-panel-body-dark
|
||||
space-y-6
|
||||
py-8
|
||||
"
|
||||
>
|
||||
<Formatter />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="w-1/2 text-center flex flex-col gap-2">
|
||||
<div className="flex flex-col gap-1">
|
||||
<h3 className="text-sm text-scale-1200">Select an Event</h3>
|
||||
<p className="text-xs text-scale-1100">
|
||||
<p className="text-xs text-scale-900">
|
||||
Select an Event to view the code snippet (pretty view) or complete JSON payload (raw
|
||||
view).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex w-full grow">
|
||||
<div
|
||||
className="
|
||||
flex-grow overflow-y-auto
|
||||
bg-scale-300
|
||||
space-y-6
|
||||
py-4
|
||||
"
|
||||
>
|
||||
<div
|
||||
className="transition absolute cursor-pointer top-5 right-5 text-scale-900 hover:text-scale-1200"
|
||||
onClick={onClose}
|
||||
>
|
||||
<IconX size={14} strokeWidth={2} />
|
||||
</div>
|
||||
<div className="flex flex-col space-y-6">{log && <Formatter />}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
+7
-3
@@ -1,4 +1,6 @@
|
||||
import React from 'react'
|
||||
import { LOGS_TAILWIND_CLASSES } from '../Logs.constants'
|
||||
import LogsDivider from '../Logs.Divider'
|
||||
import { jsonSyntaxHighlight, ResponseCodeFormatter } from '../LogsFormatters'
|
||||
|
||||
const DatabaseApiSelectionRender = ({ log }: any) => {
|
||||
@@ -22,7 +24,7 @@ const DatabaseApiSelectionRender = ({ log }: any) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="px-5 space-y-2">
|
||||
<div className={`${LOGS_TAILWIND_CLASSES.log_selection_x_padding} space-y-2`}>
|
||||
<DetailedRow label="Status" value={<ResponseCodeFormatter value={status} />} />
|
||||
<DetailedRow label="Method" value={method} />
|
||||
<DetailedRow label="Timestamp" value={log.timestamp} />
|
||||
@@ -31,7 +33,8 @@ const DatabaseApiSelectionRender = ({ log }: any) => {
|
||||
{clientInfo && <DetailedRow label="Client" value={clientInfo} />}
|
||||
{referer && <DetailedRow label="Referer" value={referer} />}
|
||||
</div>
|
||||
<div className="px-5">
|
||||
<LogsDivider />
|
||||
<div className={`${LOGS_TAILWIND_CLASSES.log_selection_x_padding}`}>
|
||||
<h3 className="text-lg text-scale-1200 mb-4">Request body</h3>
|
||||
<pre className="text-sm syntax-highlight overflow-x-auto">
|
||||
<div
|
||||
@@ -42,7 +45,8 @@ const DatabaseApiSelectionRender = ({ log }: any) => {
|
||||
/>
|
||||
</pre>
|
||||
</div>
|
||||
<div className="px-5">
|
||||
<LogsDivider />
|
||||
<div className={`${LOGS_TAILWIND_CLASSES.log_selection_x_padding}`}>
|
||||
<h3 className="text-lg text-scale-1200 mb-4">
|
||||
Response{method ? ` ${method}` : null} body
|
||||
</h3>
|
||||
|
||||
+8
-8
@@ -1,5 +1,7 @@
|
||||
import { Alert } from '@supabase/ui'
|
||||
import React from 'react'
|
||||
import { LOGS_TAILWIND_CLASSES } from '../Logs.constants'
|
||||
import LogsDivider from '../Logs.Divider'
|
||||
import { jsonSyntaxHighlight, SeverityFormatter } from '../LogsFormatters'
|
||||
|
||||
const DatabasePostgresSelectionRender = ({ log }: any) => {
|
||||
@@ -18,7 +20,7 @@ const DatabasePostgresSelectionRender = ({ log }: any) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="px-5">
|
||||
<div className={LOGS_TAILWIND_CLASSES.log_selection_x_padding}>
|
||||
<span className="text-scale-900 text-sm col-span-4">Event message</span>
|
||||
|
||||
<div
|
||||
@@ -28,21 +30,19 @@ const DatabasePostgresSelectionRender = ({ log }: any) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="h-px w-full bg-panel-border-interior-light dark:bg-panel-border-interior-dark"></div>
|
||||
<div className="px-5 space-y-2">
|
||||
<LogsDivider />
|
||||
<div className={`${LOGS_TAILWIND_CLASSES.log_selection_x_padding} space-y-2`}>
|
||||
<DetailedRow label="Severity" value={<SeverityFormatter value={log.error_severity} />} />
|
||||
<DetailedRow label="Postgres Username" value={postgresUsername} />
|
||||
<DetailedRow label="Session ID" value={sessionId} />
|
||||
</div>
|
||||
|
||||
{hint && (
|
||||
<div className="mt-4 px-5">
|
||||
<div className={`mt-4 ${LOGS_TAILWIND_CLASSES.log_selection_x_padding}`}>
|
||||
<Alert variant="warning" withIcon title={log?.metadata[0]?.parsed[0]?.hint} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="h-px w-full bg-panel-border-interior-light dark:bg-panel-border-interior-dark"></div>
|
||||
<div className="px-5">
|
||||
<LogsDivider />
|
||||
<div className={LOGS_TAILWIND_CLASSES.log_selection_x_padding}>
|
||||
<h3 className="text-lg text-scale-1200 mb-4">Metadata</h3>
|
||||
<pre className="text-sm syntax-highlight overflow-x-auto">
|
||||
<div
|
||||
|
||||
@@ -259,15 +259,19 @@ const LogTable = ({ data = [], queryType }: Props) => {
|
||||
}}
|
||||
onRowClick={(r) => setFocusedLog(r)}
|
||||
/>
|
||||
{focusedLog && (
|
||||
<div className="w-1/2 flex flex-col">
|
||||
<LogSelection
|
||||
onClose={() => setFocusedLog(null)}
|
||||
log={focusedLog}
|
||||
queryType={queryType}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* {focusedLog && ( */}
|
||||
<div
|
||||
className={
|
||||
queryType ? 'w-1/2 flex flex-col' : focusedLog ? 'w-1/2 flex flex-col' : 'w-0 hidden'
|
||||
}
|
||||
>
|
||||
<LogSelection
|
||||
onClose={() => setFocusedLog(null)}
|
||||
log={focusedLog}
|
||||
queryType={queryType}
|
||||
/>
|
||||
</div>
|
||||
{/* )} */}
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
const LogsDivider = () => {
|
||||
return (
|
||||
<div className="h-px w-full bg-panel-border-interior-light dark:bg-panel-border-interior-dark"></div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LogsDivider
|
||||
@@ -253,6 +253,13 @@ export const SQL_FILTER_TEMPLATES: any = {
|
||||
'status_code.success': `response.status_code between 200 and 299`,
|
||||
'status_code.warning': `response.status_code between 400 and 499`,
|
||||
},
|
||||
function_logs: {
|
||||
'severity.error': `metadata.level = 'error'`,
|
||||
'severity.notError': `metadata.level != 'error'`,
|
||||
'severity.log': `metadata.level = 'log'`,
|
||||
'severity.info': `metadata.level = 'info'`,
|
||||
'severity.debug': `metadata.level = 'debug'`,
|
||||
},
|
||||
}
|
||||
|
||||
// export const genDefaultQuery = (table: string, where: string = ''): string => `SELECT
|
||||
@@ -366,13 +373,8 @@ export const FILTER_OPTIONS: FilterOptions = {
|
||||
key: 'product',
|
||||
options: [
|
||||
{
|
||||
key: 'realtime',
|
||||
label: 'Realtime',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
key: 'storage',
|
||||
label: 'Storage',
|
||||
key: 'database',
|
||||
label: 'Database',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
@@ -381,8 +383,13 @@ export const FILTER_OPTIONS: FilterOptions = {
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
key: 'database',
|
||||
label: 'Database',
|
||||
key: 'storage',
|
||||
label: 'Storage',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
key: 'realtime',
|
||||
label: 'Realtime',
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
@@ -433,4 +440,38 @@ export const FILTER_OPTIONS: FilterOptions = {
|
||||
],
|
||||
},
|
||||
},
|
||||
// function_logs
|
||||
function_logs: {
|
||||
severity: {
|
||||
label: 'Severity',
|
||||
key: 'severity',
|
||||
options: [
|
||||
{
|
||||
key: 'error',
|
||||
label: 'Error',
|
||||
description: 'Show all events that have error severity',
|
||||
},
|
||||
{
|
||||
key: 'info',
|
||||
label: 'Info',
|
||||
description: 'Show all events that have error severity',
|
||||
},
|
||||
{
|
||||
key: 'debug',
|
||||
label: 'Debug',
|
||||
description: 'Show all events that have error severity',
|
||||
},
|
||||
{
|
||||
key: 'log',
|
||||
label: 'Log',
|
||||
description: 'Show all events that are log severity',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const LOGS_TAILWIND_CLASSES = {
|
||||
log_selection_x_padding: 'px-8',
|
||||
space_y: 'px-6',
|
||||
}
|
||||
@@ -76,10 +76,10 @@ export const LogsFilter = ({ options, filtersState, dispatchFilters }: any) => {
|
||||
}
|
||||
})
|
||||
|
||||
// console.log('payload', payload)
|
||||
console.log('payload', payload)
|
||||
// console.log('submit form ran')
|
||||
dispatchFilters({ ...payload })
|
||||
handleReset()
|
||||
// handleReset()
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting }: { isSubmitting: boolean }) => (
|
||||
|
||||
@@ -6,8 +6,6 @@ export function filterSqlWhereBuilder(
|
||||
table: LogsTableName,
|
||||
override?: Override
|
||||
) {
|
||||
let count = 0
|
||||
|
||||
// remove any filter arrays that are empty
|
||||
const filtersSanitized: any = Object.values(filters).filter((x: any) => x && x.length > 0)
|
||||
|
||||
@@ -21,14 +19,17 @@ export function filterSqlWhereBuilder(
|
||||
if (filtersSanitized.length === 0 && !hasOverride) return whereArray
|
||||
|
||||
if (hasOverride) {
|
||||
count = +1
|
||||
const sql = `${override?.key}='${override?.value}'`
|
||||
console.log('HAS OVERRIDE')
|
||||
// count = +1
|
||||
const sql = `(${override?.key}='${override?.value}')`
|
||||
whereArray.push(sql)
|
||||
if (filtersSanitized.length > 0) whereArray.push('and')
|
||||
}
|
||||
|
||||
if (filtersSanitized.length === 0) return whereArray
|
||||
|
||||
keys.map((x: string, i) => {
|
||||
let count = 0
|
||||
// do not parse empty key
|
||||
if (!x) return
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ export const LogsPreviewer: React.FC<Props> = ({ projectRef, queryType, override
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col flex-grow gap-4">
|
||||
<div className="h-full flex flex-col flex-grow">
|
||||
<PreviewFilterPanel
|
||||
isShowingEventChart={showChart}
|
||||
onToggleEventChart={() => setShowChart(!showChart)}
|
||||
@@ -162,7 +162,12 @@ export const LogsPreviewer: React.FC<Props> = ({ projectRef, queryType, override
|
||||
table={table}
|
||||
condensedLayout={condensedLayout}
|
||||
/>
|
||||
{showChart && !isLoading ? (
|
||||
<div
|
||||
className={
|
||||
'transition-all duration-500 ' +
|
||||
(showChart && !isLoading ? 'opacity-100 h-48 pt-4 mb-4' : 'opacity-0 h-0')
|
||||
}
|
||||
>
|
||||
<div className={condensedLayout ? 'px-4' : ''}>
|
||||
<LogEventChart
|
||||
data={!isLoading ? logData : undefined}
|
||||
@@ -171,8 +176,8 @@ export const LogsPreviewer: React.FC<Props> = ({ projectRef, queryType, override
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex flex-col flex-grow relative">
|
||||
</div>
|
||||
<div className="flex flex-col flex-grow relative pt-4">
|
||||
{isLoading && <div className="logs-shimmering-loader w-full h-0.5"></div>}
|
||||
<ShimmerLine active={isLoading} />
|
||||
<LoadingOpacity active={isLoading}>
|
||||
|
||||
Reference in new issue
Block a user