mirror of
https://github.com/supabase/supabase.git
synced 2026-10-12 04:45:08 +03:00
* Add shimmering-loader CSS to ui-patterns. * Import the shimmering-loader classes from the ui-patterns component. * Remove ShimmeringLoader from studio. * Migrate studio to use ui-patterns/ShimmeringLoader. * Migrate away from using default import for ShimmeringLoader. * Fix the css imports in docs and studio.
164 lines
5.7 KiB
TypeScript
164 lines
5.7 KiB
TypeScript
import { useDebounce } from '@uidotdev/usehooks'
|
|
import { Home } from 'lucide-react'
|
|
import { useState } from 'react'
|
|
|
|
import { useParams } from 'common'
|
|
import { useContentQuery } from 'data/content/content-query'
|
|
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
|
|
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
|
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
|
|
import { Metric, METRIC_CATEGORIES, METRICS } from 'lib/constants/metrics'
|
|
import type { Dashboards } from 'types'
|
|
import {
|
|
Command_Shadcn_,
|
|
CommandEmpty_Shadcn_,
|
|
CommandGroup_Shadcn_,
|
|
CommandInput_Shadcn_,
|
|
CommandItem_Shadcn_,
|
|
CommandList_Shadcn_,
|
|
DropdownMenuCheckboxItem,
|
|
DropdownMenuPortal,
|
|
DropdownMenuSub,
|
|
DropdownMenuSubContent,
|
|
DropdownMenuSubTrigger,
|
|
SQL_ICON,
|
|
} from 'ui'
|
|
import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
|
|
import { DEPRECATED_REPORTS } from './Reports.constants'
|
|
|
|
interface MetricOptionsProps {
|
|
config?: Dashboards.Content
|
|
handleChartSelection: ({
|
|
metric,
|
|
isAddingChart,
|
|
}: {
|
|
metric: Metric
|
|
isAddingChart: boolean
|
|
}) => void
|
|
}
|
|
|
|
export const MetricOptions = ({ config, handleChartSelection }: MetricOptionsProps) => {
|
|
const { ref: projectRef } = useParams()
|
|
const { data: selectedOrganization } = useSelectedOrganizationQuery()
|
|
const [search, setSearch] = useState('')
|
|
|
|
const { projectAuthAll: authEnabled, projectStorageAll: storageEnabled } = useIsFeatureEnabled([
|
|
'project_auth:all',
|
|
'project_storage:all',
|
|
])
|
|
|
|
const metricCategories = Object.values(METRIC_CATEGORIES).filter(({ key }) => {
|
|
if (key === 'api_auth') return authEnabled
|
|
if (key === 'api_storage') return storageEnabled
|
|
return true
|
|
})
|
|
|
|
const { mutate: sendEvent } = useSendEventMutation()
|
|
|
|
const debouncedSearch = useDebounce(search, 300)
|
|
const { data, isPending: isLoading } = useContentQuery({
|
|
projectRef,
|
|
type: 'sql',
|
|
name: debouncedSearch.length === 0 ? undefined : debouncedSearch,
|
|
})
|
|
const snippets = data?.content
|
|
|
|
return (
|
|
<>
|
|
{metricCategories.map((cat) => {
|
|
return (
|
|
<DropdownMenuSub key={cat.key}>
|
|
<DropdownMenuSubTrigger className="space-x-2">
|
|
{cat.icon ? cat.icon() : <Home size={14} />}
|
|
<p>{cat.label}</p>
|
|
</DropdownMenuSubTrigger>
|
|
<DropdownMenuPortal>
|
|
<DropdownMenuSubContent>
|
|
{METRICS.filter(
|
|
(metric) =>
|
|
!DEPRECATED_REPORTS.includes(metric.key) && metric?.category?.key === cat.key
|
|
).map((metric) => {
|
|
return (
|
|
<DropdownMenuCheckboxItem
|
|
key={metric.key}
|
|
className="cursor-pointer"
|
|
checked={config?.layout?.some((x: any) => x.attribute === metric.key)}
|
|
onCheckedChange={(e) => handleChartSelection({ metric, isAddingChart: e })}
|
|
>
|
|
<div className="flex flex-col space-y-0">
|
|
<span>{metric.label}</span>
|
|
</div>
|
|
</DropdownMenuCheckboxItem>
|
|
)
|
|
})}
|
|
</DropdownMenuSubContent>
|
|
</DropdownMenuPortal>
|
|
</DropdownMenuSub>
|
|
)
|
|
})}
|
|
<DropdownMenuSub>
|
|
<DropdownMenuSubTrigger className="space-x-2">
|
|
<SQL_ICON
|
|
size={14}
|
|
strokeWidth={1.5}
|
|
className="fill-foreground-light w-5 h-4 shrink-0 grow-0 -ml-0.5"
|
|
/>
|
|
<p>SQL Snippets</p>
|
|
</DropdownMenuSubTrigger>
|
|
<DropdownMenuPortal>
|
|
<DropdownMenuSubContent className="p-0">
|
|
<Command_Shadcn_ shouldFilter={false}>
|
|
<CommandInput_Shadcn_
|
|
autoFocus
|
|
placeholder="Search snippets..."
|
|
value={search}
|
|
onValueChange={setSearch}
|
|
/>
|
|
<CommandList_Shadcn_>
|
|
{isLoading ? (
|
|
<div className="flex flex-col p-1 gap-y-1">
|
|
<ShimmeringLoader />
|
|
<ShimmeringLoader className="w-3/4" />
|
|
</div>
|
|
) : (
|
|
<CommandEmpty_Shadcn_>No snippets found</CommandEmpty_Shadcn_>
|
|
)}
|
|
<CommandGroup_Shadcn_>
|
|
{snippets?.map((snippet) => (
|
|
<CommandItem_Shadcn_
|
|
key={snippet.id}
|
|
value={snippet.id}
|
|
className="cursor-pointer"
|
|
onSelect={() => {
|
|
if (!config?.layout.find((x) => x.id === snippet.id)) {
|
|
handleChartSelection({
|
|
metric: {
|
|
id: snippet.id,
|
|
key: `snippet_${snippet.id}`,
|
|
label: snippet.name,
|
|
},
|
|
isAddingChart: true,
|
|
})
|
|
sendEvent({
|
|
action: 'custom_report_add_sql_block_clicked',
|
|
groups: {
|
|
project: projectRef ?? 'Unknown',
|
|
organization: selectedOrganization?.slug ?? 'Unknown',
|
|
},
|
|
})
|
|
}
|
|
}}
|
|
>
|
|
{snippet.name}
|
|
</CommandItem_Shadcn_>
|
|
))}
|
|
</CommandGroup_Shadcn_>
|
|
</CommandList_Shadcn_>
|
|
</Command_Shadcn_>
|
|
</DropdownMenuSubContent>
|
|
</DropdownMenuPortal>
|
|
</DropdownMenuSub>
|
|
</>
|
|
)
|
|
}
|