SQL preview on hover snippet (#20694)

* SQL preview on hover snippet

* Fix class name

* Fix some styling

* Fix some styling

* Remove console log

* Fix
This commit is contained in:
Joshen Lim authored and GitHub committed 2024-01-24 16:07:05 +07:00
1 parent 2eb113eadf
commit ff8b855678
8 files changed
+85 -42

No files matched your search

@@ -39,7 +39,6 @@ export const SelectionDetailedRow = ({
</span>
{!hideCopy && (
<CopyButton
bounceIconOnCopy
text={value}
className="group-hover:opacity-100 opacity-0 my-auto transition col-span-2 h-4 w-4 px-0 py-0"
type="text"
@@ -210,7 +210,7 @@ const SQLEditor = () => {
range: new monaco.Range(line, 1, line, 20),
options: {
isWholeLine: true,
inlineClassName: 'bg-amber-600',
inlineClassName: 'bg-warning-400',
},
},
]
@@ -38,7 +38,6 @@ export const SelectionDetailedRow = ({
{valueRender ?? value}
</span>
<CopyButton
bounceIconOnCopy
text={value}
className="group-hover:opacity-100 opacity-0 my-auto transition col-span-2 h-4 w-4 px-0 py-0"
type="text"
@@ -26,12 +26,17 @@ import {
IconTrash,
IconUnlock,
Modal,
TooltipContent_Shadcn_,
TooltipTrigger_Shadcn_,
Tooltip_Shadcn_,
} from 'ui'
import DownloadSnippetModal from 'components/interfaces/SQLEditor/DownloadSnippetModal'
import RenameQueryModal from 'components/interfaces/SQLEditor/RenameQueryModal'
import { createSqlSnippetSkeleton } from 'components/interfaces/SQLEditor/SQLEditor.utils'
import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock'
import ConfirmationModal from 'components/ui/ConfirmationModal'
import CopyButton from 'components/ui/CopyButton'
import { useContentDeleteMutation } from 'data/content/content-delete-mutation'
import { SqlSnippet } from 'data/content/sql-snippets-query'
import { useCheckPermissions, useSelectedProject, useStore } from 'hooks'
@@ -46,7 +51,7 @@ export interface QueryItemProps {
const QueryItem = ({ tabInfo }: QueryItemProps) => {
const { ref, id: activeId } = useParams()
const { id, name, description } = tabInfo || {}
const { id, name, description, content } = tabInfo || {}
const isActive = id === activeId
const activeItemRef = useRef<HTMLElement | null>(null)
@@ -61,24 +66,64 @@ const QueryItem = ({ tabInfo }: QueryItemProps) => {
})
return (
<div
key={id}
className={clsx(
'flex items-center justify-between rounded-md group',
isActive && 'text-foreground bg-surface-300 -active'
)}
ref={isActive ? (activeItemRef as React.RefObject<HTMLDivElement>) : null}
>
<Link href={`/project/${ref}/sql/${id}`} className="py-1 px-3 w-full overflow-hidden">
<p
title={description || name}
className="text-sm text-foreground-light group-hover:text-foreground transition overflow-hidden text-ellipsis"
<Tooltip_Shadcn_ delayDuration={100}>
<TooltipTrigger_Shadcn_ asChild>
<div
key={id}
className={clsx(
'flex items-center justify-between rounded-md group',
isActive ? 'bg-surface-300' : 'hover:bg-surface-200'
)}
ref={isActive ? (activeItemRef as React.RefObject<HTMLDivElement>) : null}
>
{name}
</p>
</Link>
<div className="pr-1">{<QueryItemActions tabInfo={tabInfo} activeId={activeId} />}</div>
</div>
<Link href={`/project/${ref}/sql/${id}`} className="py-1 px-3 w-full overflow-hidden">
<p
title={description || name}
className={clsx(
isActive
? 'text-foreground'
: 'text-foreground-light group-hover:text-foreground/80',
'text-sm transition overflow-hidden text-ellipsis'
)}
>
{name}
</p>
</Link>
<div className="pr-1">{<QueryItemActions tabInfo={tabInfo} activeId={activeId} />}</div>
</div>
</TooltipTrigger_Shadcn_>
{!isActive && (
<TooltipContent_Shadcn_
side="right"
align="start"
className="w-96 flex flex-col gap-y-2 py-3 -translate-y-[4px]"
>
<p className="text-xs">Query preview:</p>
<div className="bg-surface-300 py-2 px-3 rounded relative">
{content.sql.trim() ? (
<SimpleCodeBlock
showCopy={false}
className="sql"
parentClassName="!p-0 [&>div>span]:text-xs [&>div>span]:tracking-tighter"
>
{content.sql.replaceAll('\n', ' ').replaceAll(/\s+/g, ' ').slice(0, 43) +
`${content.sql.length > 43 ? '...' : ''}`}
</SimpleCodeBlock>
) : (
<p className="text-xs text-foreground-lighter">This query is empty</p>
)}
{content.sql.trim() && (
<CopyButton
iconOnly
type="default"
className="px-1 absolute top-1.5 right-1.5"
text={content.sql}
/>
)}
</div>
</TooltipContent_Shadcn_>
)}
</Tooltip_Shadcn_>
)
}
@@ -225,7 +270,7 @@ const QueryItemActions = observer(({ tabInfo, activeId }: QueryItemActionsProps)
<IconChevronDown size="tiny" strokeWidth={2} />
</span>
</DropdownMenuTrigger>
<DropdownMenuContent side="bottom" align="end">
<DropdownMenuContent side="bottom" align="end" className=" w-52 translate-x-[4px]">
{isSnippetOwner && (
<DropdownMenuItem onClick={onClickRename} className="space-x-2">
<IconEdit2 size="tiny" />
@@ -3,7 +3,7 @@ import { useParams } from 'common'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/router'
import { useMemo, useState } from 'react'
import { Button, cn, IconPlus, IconSearch, IconX, Input, Menu } from 'ui'
import { Button, IconPlus, IconSearch, IconX, Input, Menu, cn } from 'ui'
import { untitledSnippetTitle } from 'components/interfaces/SQLEditor/SQLEditor.constants'
import { createSqlSnippetSkeleton } from 'components/interfaces/SQLEditor/SQLEditor.utils'
@@ -20,6 +20,7 @@ const prism = {
}
interface SimpleCodeBlockProps {
parentClassName?: string
className?: string
metastring?: string
showCopy?: boolean
@@ -27,6 +28,7 @@ interface SimpleCodeBlockProps {
const SimpleCodeBlock = ({
children,
parentClassName,
className: languageClassName,
metastring,
showCopy = true,
@@ -67,7 +69,7 @@ const SimpleCodeBlock = ({
{({ className, tokens, getLineProps, getTokenProps }) => {
return (
<div className="Code codeBlockWrapper group">
<pre ref={target} className={`codeBlock ${className}`}>
<pre ref={target} className={`codeBlock ${className} ${parentClassName}`}>
{tokens.map((line, i) => {
const lineProps = getLineProps({ line, key: i })
+9 -18
View File
@@ -1,20 +1,12 @@
import { Button, ButtonProps } from 'ui'
import { Button, ButtonProps, IconCheck, IconClipboard } from 'ui'
import { copyToClipboard } from 'lib/helpers'
import { IconClipboard } from 'ui'
import { useEffect, useState } from 'react'
export interface CopyButtonProps extends ButtonProps {
text: string
// used for text-less feedback
bounceIconOnCopy?: boolean
iconOnly?: boolean
}
const CopyButton: React.FC<CopyButtonProps> = ({
text,
children,
onClick,
bounceIconOnCopy,
...props
}) => {
const CopyButton = ({ text, iconOnly = false, children, onClick, ...props }: CopyButtonProps) => {
const [showCopied, setShowCopied] = useState(false)
useEffect(() => {
@@ -31,16 +23,15 @@ const CopyButton: React.FC<CopyButtonProps> = ({
onClick?.(e)
}}
icon={
<IconClipboard
size="tiny"
className={[showCopied && bounceIconOnCopy ? 'animate-bounce' : '', 'transition'].join(
' '
)}
/>
showCopied ? (
<IconCheck size="tiny" strokeWidth={2} className="text-brand" />
) : (
<IconClipboard size="tiny" />
)
}
{...props}
>
{children ?? (showCopied ? 'Copied' : 'Copy')}
{!iconOnly && <>{children ?? (showCopied ? 'Copied' : 'Copy')}</>}
</Button>
)
}
+7
View File
@@ -196,6 +196,13 @@ export {
TabsTrigger as TabsTrigger_Shadcn_,
} from './src/components/shadcn/ui/tabs/tabs'
export {
TooltipProvider as TooltipProvider_Shadcn_,
Tooltip as Tooltip_Shadcn_,
TooltipTrigger as TooltipTrigger_Shadcn_,
TooltipContent as TooltipContent_Shadcn_,
} from './src/components/shadcn/ui/tooltip'
export { ScrollArea, ScrollBar } from './src/components/shadcn/ui/scroll-area'
export { Separator } from './src/components/shadcn/ui/separator'