templates.tsx101 lines · main
1import { useParams } from 'common'
2import { CodeIcon } from 'lucide-react'
3import { useState } from 'react'
4import { Button, cn, Popover, PopoverContent, PopoverTrigger } from 'ui'
5
6import { TEMPLATES } from '@/components/interfaces/Settings/Logs/Logs.constants'
7import type { LogTemplate } from '@/components/interfaces/Settings/Logs/Logs.types'
8import DefaultLayout from '@/components/layouts/DefaultLayout'
9import LogsLayout from '@/components/layouts/LogsLayout/LogsLayout'
10import CardButton from '@/components/ui/CardButton'
11import LogsExplorerHeader from '@/components/ui/Logs/LogsExplorerHeader'
12import { UnknownInterface } from '@/components/ui/UnknownInterface'
13import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
14import type { NextPageWithLayout } from '@/types'
15
16export const LogsTemplatesPage: NextPageWithLayout = () => {
17 const { ref: projectRef } = useParams()
18 const { logsTemplates: isTemplatesEnabled, logsShowMetadataIpTemplate: showMetadataIpTemplate } =
19 useIsFeatureEnabled(['logs:templates', 'logs:show_metadata_ip_template'])
20
21 if (!isTemplatesEnabled) {
22 return <UnknownInterface urlBack={`/project/${projectRef}/logs/explorer`} />
23 }
24
25 const allTemplates = showMetadataIpTemplate
26 ? TEMPLATES
27 : TEMPLATES.filter((template) => template.label !== 'Metadata IP')
28
29 return (
30 <div className="mx-auto h-full w-full px-5 py-6">
31 <LogsExplorerHeader subtitle="Templates" />
32 <div className="grid lg:grid-cols-3 gap-6 mt-4 pb-24">
33 {allTemplates
34 .sort((a, b) => a.label!.localeCompare(b.label!))
35 .filter((template) => template.mode === 'custom')
36 .map((template, i) => {
37 return <Template key={i} projectRef={projectRef} template={template} />
38 })}
39 </div>
40 </div>
41 )
42}
43
44LogsTemplatesPage.getLayout = (page) => (
45 <DefaultLayout>
46 <LogsLayout title="Templates">{page}</LogsLayout>
47 </DefaultLayout>
48)
49
50export default LogsTemplatesPage
51
52const Template = ({ projectRef, template }: { projectRef?: string; template: LogTemplate }) => {
53 const [showPreview, setShowPreview] = useState(false)
54
55 return (
56 <CardButton
57 title={template.label}
58 icon={
59 <div
60 className={cn(
61 'duration-400 flex h-6 w-6 items-center justify-center rounded-sm transition-colors',
62 'border bg-background-200',
63 'group-hover:bg-brand-300 group-hover:text-brand-600 group-hover:border-brand-500',
64 'dark:border-background-selection dark:bg-background-200 dark:text-foreground',
65 'dark:group-hover:border-brand-600 dark:group-hover:bg-brand-300 dark:group-hover:text-brand-600'
66 )}
67 >
68 <div className="scale-100 group-hover:scale-110">
69 <CodeIcon size={12} strokeWidth={2} />
70 </div>
71 </div>
72 }
73 className="h-44"
74 linkHref={`/project/${projectRef}/logs/explorer?q=${encodeURI(template.searchString)}`}
75 description={template.description}
76 footer={
77 <div className="flex flex-row justify-end">
78 <Popover onOpenChange={setShowPreview} open={showPreview}>
79 <PopoverTrigger asChild>
80 <Button
81 asChild
82 type="default"
83 onClick={(e) => {
84 e.preventDefault()
85 setShowPreview(!showPreview)
86 }}
87 >
88 <span>Preview</span>
89 </Button>
90 </PopoverTrigger>
91 <PopoverContent className="rounded-lg bg-alternative p-0">
92 <pre className="whitespace-pre-line wrap-break-word rounded-lg bg-alternative p-4 text-sm">
93 {template.searchString}
94 </pre>
95 </PopoverContent>
96 </Popover>
97 </div>
98 }
99 />
100 )
101}