Skip to content

Commit 849c29f

Browse files
dnywhjoshenlim
andauthored
chore(studio): improve Storage UI (supabase#40367)
* clarify breadcrumbs * tiny badge variant * improve admonition * indicate max buckets limit * nit * Minor nits * badge fix --------- Co-authored-by: Joshen Lim <[email protected]>
1 parent e36ae95 commit 849c29f

File tree

13 files changed

+170
-62
lines changed

13 files changed

+170
-62
lines changed

apps/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,10 @@ export const EmailTemplates = () => {
193193
<div className="flex flex-col md:flex-row md:items-center gap-y-2 md:gap-x-8 justify-between px-2 py-1">
194194
<div className="flex flex-col gap-y-0.5">
195195
<div className="flex flex-col gap-y-2 items-start">
196-
<Badge variant="success" className="-ml-0.5">
197-
NEW
196+
<Badge variant="success" className="-ml-0.5 uppercase">
197+
New
198198
</Badge>
199-
<p className="text-sm">
199+
<p className="text-sm font-medium">
200200
Notify users about security-sensitive actions on their accounts
201201
</p>
202202
</div>

apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/SimpleConfigurationDetails.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export const SimpleConfigurationDetails = ({ bucketName }: { bucketName?: string
3737
>
3838
Learn more
3939
</InlineLink>
40-
.
4140
</ScaffoldSectionDescription>
4241
</div>
4342
<CopyEnvButton

apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ export const AnalyticBucketDetails = () => {
231231
<div className="flex flex-col items-center text-center">
232232
<h3>Connect database tables</h3>
233233
<p className="text-foreground-light text-sm">
234-
Stream data from tables for archival, backups, or analytical queries.
234+
Stream table data for continuous backups and analysis
235235
</p>
236236
</div>
237237
<ConnectTablesDialog

apps/studio/components/interfaces/Storage/AnalyticsBuckets/CreateAnalyticsBucketModal.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const CreateAnalyticsBucketModal = ({
105105

106106
const [visible, setVisible] = useState(false)
107107

108-
const { data: buckets = [] } = useAnalyticsBucketsQuery({ projectRef: ref })
108+
const { data: buckets = [], isLoading } = useAnalyticsBucketsQuery({ projectRef: ref })
109109
const icebergCatalogEnabled = useIsAnalyticsBucketsEnabled({ projectRef: ref })
110110
const wrappersExtenstionNeedsUpgrading = wrappersExtensionState === 'needs-upgrade'
111111

@@ -192,7 +192,13 @@ export const CreateAnalyticsBucketModal = ({
192192
type={buttonType}
193193
className={buttonClassName}
194194
icon={<Plus size={14} />}
195-
disabled={!canCreateBuckets || !icebergCatalogEnabled || disabled}
195+
disabled={
196+
!canCreateBuckets ||
197+
!icebergCatalogEnabled ||
198+
isLoading ||
199+
buckets.length >= 2 ||
200+
disabled
201+
}
196202
style={{ justifyContent: 'start' }}
197203
onClick={() => setVisible(true)}
198204
tooltip={{
@@ -203,7 +209,9 @@ export const CreateAnalyticsBucketModal = ({
203209
? 'Analytics buckets are not enabled for your project. Please contact support to enable it.'
204210
: !canCreateBuckets
205211
? 'You need additional permissions to create buckets'
206-
: tooltip?.content?.text,
212+
: buckets.length >= 2
213+
? 'Bucket limit reached'
214+
: tooltip?.content?.text,
207215
},
208216
}}
209217
>

apps/studio/components/interfaces/Storage/AnalyticsBuckets/index.tsx

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1-
import { ChevronRight, ExternalLink, Search } from 'lucide-react'
2-
import { useRouter } from 'next/navigation'
3-
import { useState } from 'react'
4-
51
import { useParams } from 'common'
62
import { ScaffoldHeader, ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold'
73
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
84
import { useAnalyticsBucketsQuery } from 'data/storage/analytics-buckets-query'
95
import { Bucket as BucketIcon } from 'icons'
10-
import { Button, Card, cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
6+
import { BASE_PATH } from 'lib/constants'
7+
import { ChevronRight, ExternalLink, Search } from 'lucide-react'
8+
import Link from 'next/link'
9+
import { useRouter } from 'next/navigation'
10+
import { useState } from 'react'
11+
import {
12+
Badge,
13+
Button,
14+
Card,
15+
cn,
16+
Table,
17+
TableBody,
18+
TableCell,
19+
TableHead,
20+
TableHeader,
21+
TableRow,
22+
Tooltip,
23+
TooltipContent,
24+
TooltipTrigger,
25+
} from 'ui'
1126
import { Admonition, TimestampInfo } from 'ui-patterns'
1227
import { Input } from 'ui-patterns/DataInputs/Input'
1328
import { EmptyBucketState } from '../EmptyBucketState'
@@ -41,28 +56,45 @@ export const AnalyticsBuckets = () => {
4156

4257
return (
4358
<ScaffoldSection isFullWidth>
44-
<Admonition
45-
type="note"
46-
layout="horizontal"
47-
className="-mt-4 mb-8 [&>div]:!translate-y-0 [&>svg]:!translate-y-1"
48-
title="Private alpha"
49-
actions={
50-
<Button asChild type="default" icon={<ExternalLink />}>
51-
<a
59+
<Admonition showIcon={false} type="tip" className="relative mb-6 overflow-hidden">
60+
<div className="absolute -inset-16 z-0 opacity-50">
61+
<img
62+
src={`${BASE_PATH}/img/reports/bg-grafana-dark.svg`}
63+
alt="Supabase Grafana"
64+
className="w-full h-full object-cover object-right hidden dark:block"
65+
/>
66+
<img
67+
src={`${BASE_PATH}/img/reports/bg-grafana-light.svg`}
68+
alt="Supabase Grafana"
69+
className="w-full h-full object-cover object-right dark:hidden"
70+
/>
71+
<div className="absolute inset-0 bg-gradient-to-r from-background-alternative to-transparent" />
72+
</div>
73+
74+
<div className="relative z-10 flex flex-col md:flex-row md:items-center gap-y-2 md:gap-x-8 justify-between px-2 py-1">
75+
<div className="flex flex-col gap-y-0.5">
76+
<div className="flex flex-col gap-y-2 items-start">
77+
<Badge variant="success" className="-ml-0.5 uppercase">
78+
New
79+
</Badge>
80+
<p className="text-sm font-medium">Introducing analytics buckets</p>
81+
</div>
82+
<p className="text-sm text-foreground-lighter text-balance">
83+
Analytics buckets are now in private alpha. Expect rapid changes, limited features,
84+
and possible breaking updates. Please share feedback as we refine the experience and
85+
expand access.
86+
</p>
87+
</div>
88+
<Button asChild type="default" icon={<ExternalLink strokeWidth={1.5} />} className="mt-2">
89+
<Link
90+
href="https://github.com/orgs/supabase/discussions/40116"
5291
target="_blank"
5392
rel="noopener noreferrer"
54-
href="https://github.com/orgs/supabase/discussions/40116"
5593
>
5694
Share feedback
57-
</a>
95+
</Link>
5896
</Button>
59-
}
60-
>
61-
<p className="!leading-normal !mb-0 text-balance">
62-
Analytics buckets are now in private alpha. Expect rapid changes, limited features, and
63-
possible breaking updates. Please share feedback as we refine the experience and expand
64-
access.
65-
</p>
97+
</div>
6698
</Admonition>
6799

68100
{!isLoadingBuckets &&
@@ -71,8 +103,21 @@ export const AnalyticsBuckets = () => {
71103
<EmptyBucketState bucketType="analytics" />
72104
) : (
73105
<div className="flex flex-col gap-y-4">
74-
<ScaffoldHeader className="py-0">
106+
<ScaffoldHeader className="py-0 flex flex-row items-center gap-x-2">
75107
<ScaffoldSectionTitle>Buckets</ScaffoldSectionTitle>
108+
{analyticsBuckets.length > 0 && (
109+
<Tooltip>
110+
<TooltipTrigger>
111+
<span className="bg-surface-200 rounded-full px-2 py-1 leading-none text-xs text-foreground-lighter tracking-widest">
112+
{analyticsBuckets.length}
113+
/2
114+
</span>
115+
</TooltipTrigger>
116+
<TooltipContent side="bottom" className="w-64 text-center">
117+
Each project can only have up to 2 buckets while analytics buckets are in alpha{' '}
118+
</TooltipContent>
119+
</Tooltip>
120+
)}
76121
</ScaffoldHeader>
77122
<div className="flex flex-grow justify-between gap-x-2 items-center">
78123
<Input

apps/studio/components/interfaces/Storage/Storage.constants.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,23 +66,23 @@ export const BUCKET_TYPES = {
6666
singularName: 'file',
6767
article: 'a',
6868
description: 'General file storage for most types of digital content',
69-
valueProp: 'Store images, videos, documents, and any other file type.',
69+
valueProp: 'Store images, videos, documents, and any other file type',
7070
docsUrl: `${DOCS_URL}/guides/storage/buckets/fundamentals`,
7171
},
7272
analytics: {
7373
displayName: 'Analytics',
7474
singularName: 'analytics',
7575
article: 'an',
7676
description: 'Purpose-built storage for analytical workloads',
77-
valueProp: 'Store large datasets for analytics and reporting.',
77+
valueProp: 'Store large datasets for analytics and reporting',
7878
docsUrl: `${DOCS_URL}/guides/storage/analytics/introduction`,
7979
},
8080
vectors: {
8181
displayName: 'Vectors',
8282
singularName: 'vector',
8383
article: 'a',
8484
description: 'Purpose-built storage for vector data',
85-
valueProp: 'Store, index, and query your vector embeddings at scale.',
85+
valueProp: 'Store, index, and query your vector embeddings at scale',
8686
docsUrl: `${DOCS_URL}/guides/storage/vectors`,
8787
},
8888
}

apps/studio/components/interfaces/Storage/StorageMenuV2.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const StorageMenuV2 = () => {
3535
<div className="flex items-center justify-between">
3636
<p className="truncate">{config.displayName}</p>
3737
{isAlphaEnabled && (
38-
<Badge variant="default" size="small">
38+
<Badge variant="success" size="tiny">
3939
New
4040
</Badge>
4141
)}

apps/studio/components/interfaces/Storage/VectorBuckets/index.tsx

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
import { ChevronRight, ExternalLink, Search } from 'lucide-react'
2+
import Link from 'next/link'
23
import { useRouter } from 'next/navigation'
3-
import type React from 'react'
4-
import { useState } from 'react'
4+
import { useState, type KeyboardEvent, type MouseEvent } from 'react'
55

66
import { useParams } from 'common'
77
import { ScaffoldHeader, ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold'
88
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
99
import { useVectorBucketsQuery } from 'data/storage/vector-buckets-query'
1010
import { Bucket as BucketIcon } from 'icons'
11-
import { Button, Card, cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
11+
import { BASE_PATH } from 'lib/constants'
12+
import {
13+
Badge,
14+
Button,
15+
Card,
16+
cn,
17+
Table,
18+
TableBody,
19+
TableCell,
20+
TableHead,
21+
TableHeader,
22+
TableRow,
23+
} from 'ui'
1224
import { Admonition } from 'ui-patterns'
1325
import { Input } from 'ui-patterns/DataInputs/Input'
1426
import { TimestampInfo } from 'ui-patterns/TimestampInfo'
@@ -36,10 +48,7 @@ export const VectorsBuckets = () => {
3648
bucket.vectorBucketName.toLowerCase().includes(filterString.toLowerCase())
3749
)
3850

39-
const handleBucketNavigation = (
40-
bucketName: string,
41-
event: React.MouseEvent | React.KeyboardEvent
42-
) => {
51+
const handleBucketNavigation = (bucketName: string, event: MouseEvent | KeyboardEvent) => {
4352
const url = `/project/${projectRef}/storage/vectors/buckets/${encodeURIComponent(bucketName)}`
4453
if (event.metaKey || event.ctrlKey) {
4554
window.open(url, '_blank')
@@ -50,29 +59,46 @@ export const VectorsBuckets = () => {
5059

5160
return (
5261
<ScaffoldSection isFullWidth>
53-
<Admonition
54-
type="note"
55-
layout="horizontal"
56-
className="-mt-4 mb-8 [&>div]:!translate-y-0 [&>svg]:!translate-y-1"
57-
title="Private alpha"
58-
actions={
59-
<Button asChild type="default" icon={<ExternalLink />}>
60-
<a
61-
target="_blank"
62-
rel="noopener noreferrer"
62+
<Admonition showIcon={false} type="tip" className="relative mb-6 overflow-hidden">
63+
<div className="absolute -inset-16 z-0 opacity-50">
64+
<img
65+
src={`${BASE_PATH}/img/reports/bg-grafana-dark.svg`}
66+
alt="Supabase Grafana"
67+
className="w-full h-full object-cover object-right hidden dark:block"
68+
/>
69+
<img
70+
src={`${BASE_PATH}/img/reports/bg-grafana-light.svg`}
71+
alt="Supabase Grafana"
72+
className="w-full h-full object-cover object-right dark:hidden"
73+
/>
74+
<div className="absolute inset-0 bg-gradient-to-r from-background-alternative to-transparent" />
75+
</div>
76+
77+
<div className="relative z-10 flex flex-col md:flex-row md:items-center gap-y-2 md:gap-x-8 justify-between px-2 py-1">
78+
<div className="flex flex-col gap-y-0.5">
79+
<div className="flex flex-col gap-y-2 items-start">
80+
<Badge variant="success" className="-ml-0.5 uppercase">
81+
New
82+
</Badge>
83+
<p className="text-sm font-medium">Introducing vector buckets</p>
84+
</div>
85+
<p className="text-sm text-foreground-lighter text-balance">
86+
Vector buckets are now in private alpha. Expect rapid changes, limited features, and
87+
possible breaking updates. Please share feedback as we refine the experience and
88+
expand access.
89+
</p>
90+
</div>
91+
<Button asChild type="default" icon={<ExternalLink strokeWidth={1.5} />} className="mt-2">
92+
<Link
6393
// [Joshen] To update with Vector specific GH discussion
6494
href="https://github.com/orgs/supabase/discussions/40116"
95+
target="_blank"
96+
rel="noopener noreferrer"
6597
>
6698
Share feedback
67-
</a>
99+
</Link>
68100
</Button>
69-
}
70-
>
71-
<p className="!leading-normal !mb-0 text-balance">
72-
Vector buckets are now in private alpha. Expect rapid changes, limited features, and
73-
possible breaking updates. Please share feedback as we refine the experience and expand
74-
access.
75-
</p>
101+
</div>
76102
</Admonition>
77103

78104
{!isLoadingBuckets && bucketsList.length === 0 ? (

apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const ProductMenuItem = ({
3838
>
3939
<span className="truncate flex-1">{name}</span>
4040
{label !== undefined && (
41-
<Badge variant="warning" className="py-0 px-1.5 uppercase">
41+
<Badge variant="warning" size="tiny">
4242
{label}
4343
</Badge>
4444
)}

apps/studio/pages/project/[ref]/storage/analytics/buckets/[bucketId].tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PageLayout } from 'components/layouts/PageLayout/PageLayout'
66
import StorageLayout from 'components/layouts/StorageLayout/StorageLayout'
77
import { DocsButton } from 'components/ui/DocsButton'
88
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
9+
import { Bucket as BucketIcon } from 'icons'
910
import type { NextPageWithLayout } from 'types'
1011

1112
const AnalyticsBucketPage: NextPageWithLayout = () => {
@@ -16,11 +17,19 @@ const AnalyticsBucketPage: NextPageWithLayout = () => {
1617
return (
1718
<PageLayout
1819
title={bucketId}
20+
icon={
21+
<div className="shrink-0 w-10 h-10 relative bg-surface-100 border rounded-md flex items-center justify-center">
22+
<BucketIcon size={20} className="text-foreground-light" />
23+
</div>
24+
}
1925
breadcrumbs={[
2026
{
2127
label: 'Analytics',
2228
href: `/project/${project?.ref}/storage/analytics`,
2329
},
30+
{
31+
label: 'Buckets',
32+
},
2433
]}
2534
secondaryActions={config?.docsUrl ? [<DocsButton key="docs" href={config.docsUrl} />] : []}
2635
>

0 commit comments

Comments
 (0)