mirror of
https://github.com/supabase/supabase.git
synced 2026-10-17 15:19:08 +03:00
* Switch all top-level imports for ui-patterns components to use specific components when importing. * Remove the @ui-patterns shorthand since it works exactly the same without the @. * More import fixes. * Fix the ui-patterns tests.
114 lines
3.6 KiB
TypeScript
114 lines
3.6 KiB
TypeScript
'use client'
|
|
import { useEffect, useRef, useState } from 'react'
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui/src/components/shadcn/ui/tooltip'
|
|
import { cn } from 'ui/src/lib/utils'
|
|
|
|
import dayjs from 'dayjs'
|
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
|
import utc from 'dayjs/plugin/utc'
|
|
|
|
dayjs.extend(relativeTime)
|
|
dayjs.extend(utc)
|
|
|
|
const unixMicroToIsoTimestamp = (unix: string | number): string => {
|
|
return dayjs.unix(Number(unix) / 1000 / 1000).toISOString()
|
|
}
|
|
|
|
const isUnixMicro = (unix: string | number): boolean => {
|
|
const digitLength = String(unix).length === 16
|
|
const isNum = !Number.isNaN(Number(unix))
|
|
return isNum && digitLength
|
|
}
|
|
|
|
const timestampLocalFormatter = (value: string | number) => {
|
|
const timestamp = isUnixMicro(value) ? unixMicroToIsoTimestamp(value) : value
|
|
return dayjs(timestamp).format('DD MMM HH:mm:ss')
|
|
}
|
|
|
|
const timestampUtcFormatter = (value: string | number) => {
|
|
const timestamp = isUnixMicro(value) ? unixMicroToIsoTimestamp(value) : value
|
|
return dayjs(timestamp).utc().format('DD MMM HH:mm:ss')
|
|
}
|
|
|
|
const timestampRelativeFormatter = (value: string | number) => {
|
|
const timestamp = isUnixMicro(value) ? unixMicroToIsoTimestamp(value) : value
|
|
return dayjs(timestamp).fromNow()
|
|
}
|
|
|
|
export const TimestampInfo = ({
|
|
value,
|
|
className,
|
|
}: {
|
|
className?: string
|
|
value: string | number
|
|
}) => {
|
|
const local = timestampLocalFormatter(value)
|
|
const utc = timestampUtcFormatter(value)
|
|
const relative = timestampRelativeFormatter(value)
|
|
const [align, setAlign] = useState<'start' | 'end'>('start')
|
|
const triggerRef = useRef<HTMLButtonElement>(null)
|
|
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
|
|
// Calculate alignment based on trigger position
|
|
// Needed so that the tooltip isn't hidden behind the header on top rows
|
|
useEffect(() => {
|
|
const updateAlignment = () => {
|
|
if (triggerRef.current) {
|
|
const rect = triggerRef.current.getBoundingClientRect()
|
|
const windowHeight = window.innerHeight
|
|
setAlign(rect.top < windowHeight / 2 ? 'start' : 'end')
|
|
}
|
|
}
|
|
|
|
updateAlignment()
|
|
window.addEventListener('scroll', updateAlignment)
|
|
window.addEventListener('resize', updateAlignment)
|
|
|
|
return () => {
|
|
window.removeEventListener('scroll', updateAlignment)
|
|
window.removeEventListener('resize', updateAlignment)
|
|
}
|
|
}, [])
|
|
|
|
const TooltipRow = ({ label, value }: { label: string; value: string }) => {
|
|
const [copied, setCopied] = useState(false)
|
|
|
|
return (
|
|
<span
|
|
onClick={(e) => {
|
|
e.stopPropagation()
|
|
navigator.clipboard.writeText(value)
|
|
setCopied(true)
|
|
|
|
setTimeout(() => {
|
|
setCopied(false)
|
|
}, 1000)
|
|
}}
|
|
className={cn('grid grid-cols-2 gap-2 hover:bg-surface-100 px-2 py-1', {
|
|
'bg-surface-100': copied,
|
|
})}
|
|
>
|
|
<span className="text-right truncate">{label}:</span>
|
|
<span className={copied ? 'text-brand-600' : ''}>{copied ? 'Copied!' : value}</span>
|
|
</span>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger
|
|
ref={triggerRef}
|
|
className={`text-xs ${className} border-b border-transparent hover:border-dashed hover:border-foreground-light`}
|
|
>
|
|
<span>{timestampLocalFormatter(value)}</span>
|
|
</TooltipTrigger>
|
|
<TooltipContent align={align} side="right" className="font-mono p-0 py-1">
|
|
<TooltipRow label="UTC" value={utc} />
|
|
<TooltipRow label={`${localTimezone}`} value={local} />
|
|
<TooltipRow label="Relative" value={relative} />
|
|
<TooltipRow label="Timestamp" value={String(value)} />
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
)
|
|
}
|