Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { LOCAL_STORAGE_KEYS } from 'common'

export const FEATURE_PREVIEWS = [
{
key: LOCAL_STORAGE_KEYS.UI_PREVIEW_NEW_STORAGE_UI,
name: 'New Storage interface',
discussionsUrl: undefined,
isNew: true,
isPlatformOnly: false,
},
{
key: LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS,
name: 'New Logs Interface',
name: 'New Logs interface',
discussionsUrl: 'https://github.com/orgs/supabase/discussions/37234',
isNew: true,
isPlatformOnly: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,18 @@ export const useIsAdvisorRulesEnabled = () => {
return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_ADVISOR_RULES]
}

export const useIsNewStorageUIEnabled = () => {
const { flags } = useFeaturePreviewContext()
return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_NEW_STORAGE_UI]
}

export const useFeaturePreviewModal = () => {
const [featurePreviewModal, setFeaturePreviewModal] = useQueryState('featurePreviewModal')

const gitlessBranchingEnabled = useFlag('gitlessBranching')
const advisorRulesEnabled = useFlag('advisorRules')
const isUnifiedLogsPreviewAvailable = useFlag('unifiedLogs')
const isNewStorageUIAvailable = useFlag('storageAnalyticsVector')

const selectedFeatureKeyFromQuery = featurePreviewModal?.trim() ?? null
const showFeaturePreviewModal = selectedFeatureKeyFromQuery !== null
Expand All @@ -130,6 +136,8 @@ export const useFeaturePreviewModal = () => {
return advisorRulesEnabled
case 'supabase-ui-preview-unified-logs':
return isUnifiedLogsPreviewAvailable
case 'new-storage-ui':
return isNewStorageUIAvailable
default:
return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CLSPreview } from './CLSPreview'
import { FEATURE_PREVIEWS } from './FeaturePreview.constants'
import { useFeaturePreviewContext, useFeaturePreviewModal } from './FeaturePreviewContext'
import { InlineEditorPreview } from './InlineEditorPreview'
import { NewStorageUIPreview } from './NewStorageUIPreview'
import { UnifiedLogsPreview } from './UnifiedLogsPreview'

const FEATURE_PREVIEW_KEY_TO_CONTENT: {
Expand All @@ -25,6 +26,7 @@ const FEATURE_PREVIEW_KEY_TO_CONTENT: {
[LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL]: <APISidePanelPreview />,
[LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS]: <CLSPreview />,
[LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS]: <UnifiedLogsPreview />,
[LOCAL_STORAGE_KEYS.UI_PREVIEW_NEW_STORAGE_UI]: <NewStorageUIPreview />,
}

const FeaturePreviewModal = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Image from 'next/image'

import { useParams } from 'common'
import { InlineLink } from 'components/ui/InlineLink'
import { BASE_PATH } from 'lib/constants'
import { useIsNewStorageUIEnabled } from './FeaturePreviewContext'

export const NewStorageUIPreview = () => {
const { ref } = useParams()
const isStorageV2 = useIsNewStorageUIEnabled()

return (
<div className="text-sm text-foreground-light">
<p className=" mb-4">
Experience our enhanced{' '}
<InlineLink href={`/project/${ref ?? '_'}/storage/${isStorageV2 ? 'files' : 'buckets'}`}>
Storage interface
</InlineLink>{' '}
with support for analytics and vector bucket types.
</p>
<Image
alt="new-storage-preview"
src={`${BASE_PATH}/img/previews/new-storage-preview.png`}
width={1160}
height={658}
className="rounded border mb-4"
/>
<div className="space-y-2 !mt-4">
<p className="text-foreground">Enabling this preview will:</p>
<ul className="list-disc pl-6 space-y-1">
<li>Move Storage buckets from the sidebar into the main content area</li>
<li>Change the role of the sidebar to a bucket type selector</li>
<li>Nest settings and policies under their respective bucket types</li>
</ul>
<p>
These changes are necessary to support incoming analytics and vector bucket types. File
storage will remain the default, and be shown by default when entering Storage.
</p>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const UnifiedLogsPreview = () => {
className="rounded border mb-4"
/>
<p className="text-foreground-light text-sm mb-4">
Experience our enhanced logs interface with improved filtering, real-time updates, and a
Experience our enhanced Logs interface with improved filtering, real-time updates, and a
unified view across all your services. Built for better performance and easier debugging.
</p>
<p className="text-foreground-light text-sm mb-4">
Expand All @@ -26,8 +26,8 @@ export const UnifiedLogsPreview = () => {
<p className="text-sm">Enabling this preview will:</p>
<ul className="list-disc pl-6 text-sm text-foreground-light space-y-1">
<li>
Replace the current logs interface on the{' '}
<InlineLink href={`/project/${ref}/logs`}>logs page</InlineLink> with a unified view
Replace the current Logs interface on the{' '}
<InlineLink href={`/project/${ref}/logs`}>Logs page</InlineLink> with a unified view
</li>
<li>Provide enhanced filtering capabilities and real-time log streaming</li>
<li>Improve performance with optimized data loading and virtualization</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import { useRouter } from 'next/router'
import { useState } from 'react'

import { useParams } from 'common/hooks'
import Table from 'components/to-be-cleaned/Table'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query'
import type { EdgeFunctionsResponse } from 'data/edge-functions/edge-functions-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { copyToClipboard, TableCell, TableRow, Tooltip, TooltipContent, TooltipTrigger } from 'ui'

interface EdgeFunctionsListItemProps {
Expand All @@ -17,20 +16,17 @@ interface EdgeFunctionsListItemProps {
export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemProps) => {
const router = useRouter()
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const [isCopied, setIsCopied] = useState(false)

const { data: settings } = useProjectSettingsV2Query({ projectRef: ref })
const { data: customDomainData } = useCustomDomainsQuery({ projectRef: ref })

// get the .co or .net TLD from the restUrl
const restUrl = project?.restUrl
const restUrlTld = restUrl !== undefined ? new URL(restUrl).hostname.split('.').pop() : 'co'
const functionUrl = `https://${ref}.supabase.${restUrlTld}/functions/v1/${item.slug}`

const endpoint =
const protocol = settings?.app_config?.protocol ?? 'https'
const endpoint = settings?.app_config?.endpoint ?? ''
const functionUrl =
customDomainData?.customDomain?.status === 'active'
? `https://${customDomainData.customDomain.hostname}/functions/v1/${item.slug}`
: functionUrl
: `${protocol}://${endpoint}/functions/v1/${item.slug}`

return (
<TableRow
Expand All @@ -47,8 +43,8 @@ export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemP
</TableCell>
<TableCell>
<div className="text-xs text-foreground-light flex gap-2 items-center truncate">
<p title={endpoint} className="font-mono truncate hidden md:inline max-w-[30rem]">
{endpoint}
<p title={functionUrl} className="font-mono truncate hidden md:inline max-w-[30rem]">
{functionUrl}
</p>
<button
type="button"
Expand All @@ -60,7 +56,7 @@ export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemP
setTimeout(() => setIsCopied(false), 3000)
}
event.stopPropagation()
onCopy(endpoint)
onCopy(functionUrl)
}}
>
{isCopied ? (
Expand Down
10 changes: 6 additions & 4 deletions apps/studio/components/interfaces/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
} from 'ui'
import {
useIsAPIDocsSidePanelEnabled,
useIsNewStorageUIEnabled,
useUnifiedLogsPreview,
} from './App/FeaturePreview/FeaturePreviewContext'

Expand Down Expand Up @@ -222,10 +223,13 @@ const ProjectLinks = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const snap = useAppStateSnapshot()
const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled()
const { securityLints, errorLints } = useLints()
const showReports = useIsFeatureEnabled('reports:all')

const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled()
const isStorageV2 = useIsNewStorageUIEnabled()
const { isEnabled: isUnifiedLogsEnabled } = useUnifiedLogsPreview()

const activeRoute = router.pathname.split('/')[3]

const {
Expand All @@ -246,10 +250,8 @@ const ProjectLinks = () => {
edgeFunctions: edgeFunctionsEnabled,
storage: storageEnabled,
realtime: realtimeEnabled,
isStorageV2,
})

const { isEnabled: isUnifiedLogsEnabled } = useUnifiedLogsPreview()

const otherRoutes = generateOtherRoutes(ref, project, {
unifiedLogs: isUnifiedLogsEnabled,
showReports,
Expand Down
26 changes: 26 additions & 0 deletions apps/studio/components/interfaces/Storage/Storage.constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { DOCS_URL } from 'lib/constants'

// Original storage constants
export enum URL_EXPIRY_DURATION {
WEEK = 60 * 60 * 24 * 7,
MONTH = 60 * 60 * 24 * 30,
Expand Down Expand Up @@ -56,3 +59,26 @@ export const CONTEXT_MENU_KEYS = {
STORAGE_ITEM: 'STORAGE_ITEM',
STORAGE_FOLDER: 'STORAGE_FOLDER',
}

// New bucket types configuration

export const BUCKET_TYPES = {
files: {
displayName: 'Files',
description: 'General file storage for most types of digital content.',
docsUrl: `${DOCS_URL}/guides/storage/buckets/fundamentals`,
},
analytics: {
displayName: 'Analytics',
description: 'Purpose-built storage for analytical workloads.',
docsUrl: `${DOCS_URL}/guides/storage/analytics/introduction`,
},
vectors: {
displayName: 'Vectors',
description: 'Purpose-built storage for vector data.',
docsUrl: `${DOCS_URL}/guides/storage/vectors`,
},
}

export const BUCKET_TYPE_KEYS = Object.keys(BUCKET_TYPES) as Array<keyof typeof BUCKET_TYPES>
export const DEFAULT_BUCKET_TYPE: keyof typeof BUCKET_TYPES = 'files'
6 changes: 2 additions & 4 deletions apps/studio/components/interfaces/Storage/StorageMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CreateBucketModal } from 'components/interfaces/Storage/CreateBucketMod
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useBucketsQuery } from 'data/storage/buckets-query'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { IS_PLATFORM } from 'lib/constants'
import { useStorageExplorerStateSnapshot } from 'state/storage-explorer'
import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Menu } from 'ui'
import {
Expand All @@ -16,10 +17,9 @@ import {
InnerSideBarFilterSortDropdown,
InnerSideBarFilterSortDropdownItem,
} from 'ui-patterns/InnerSideMenu'
import { IS_PLATFORM } from 'lib/constants'
import { BucketRow } from './BucketRow'

const StorageMenu = () => {
export const StorageMenu = () => {
const router = useRouter()
const { ref, bucketId } = useParams()
const { data: projectDetails } = useSelectedProjectQuery()
Expand Down Expand Up @@ -169,5 +169,3 @@ const StorageMenu = () => {
</>
)
}

export default StorageMenu
30 changes: 30 additions & 0 deletions apps/studio/components/interfaces/Storage/StorageMenuV2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useParams } from 'common'
import Link from 'next/link'
import { Menu } from 'ui'
import { BUCKET_TYPES, BUCKET_TYPE_KEYS, DEFAULT_BUCKET_TYPE } from './Storage.constants'

export const StorageMenuV2 = () => {
const { ref, bucketType } = useParams()
const selectedBucketType = bucketType || DEFAULT_BUCKET_TYPE

return (
<Menu type="pills" className="mt-6 flex flex-grow flex-col">
<div className="mx-3">
<Menu.Group title={<span className="uppercase font-mono">Bucket Types</span>} />

{BUCKET_TYPE_KEYS.map((bucketTypeKey) => {
const isSelected = selectedBucketType === bucketTypeKey
const config = BUCKET_TYPES[bucketTypeKey]

return (
<Link key={bucketTypeKey} href={`/project/${ref}/storage/${bucketTypeKey}`}>
<Menu.Item rounded active={isSelected}>
<p className="truncate">{config.displayName}</p>
</Menu.Item>
</Link>
)
})}
</div>
</Menu>
)
}
23 changes: 20 additions & 3 deletions apps/studio/components/interfaces/Support/SupportFormV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { SubmitHandler, useForm } from 'react-hook-form'
import { toast } from 'sonner'
import * as z from 'zod'

import { SupportCategories } from '@supabase/shared-types/out/constants'
import { useDocsSearch, useParams, type DocsSearchResult as Page } from 'common'
import { CLIENT_LIBRARIES } from 'common/constants'
import CopyButton from 'components/ui/CopyButton'
Expand All @@ -29,6 +30,7 @@ import { useSendSupportTicketMutation } from 'data/feedback/support-ticket-send'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { getProjectDetail } from 'data/projects/project-detail-query'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { DOCS_URL } from 'lib/constants'
import { detectBrowser } from 'lib/helpers'
import { useProfile } from 'lib/profile'
Expand Down Expand Up @@ -139,6 +141,21 @@ export const SupportFormV2 = ({
const router = useRouter()
const dashboardSentryIssueId = router.query.sid as string

const isBillingEnabled = useIsFeatureEnabled('billing:all')

const categoryOptions = useMemo(() => {
return CATEGORY_OPTIONS.filter((option) => {
if (
option.value === SupportCategories.BILLING ||
option.value === SupportCategories.REFUND ||
option.value === SupportCategories.SALES_ENQUIRY
) {
return isBillingEnabled
}
return true
})
}, [isBillingEnabled])

const uploadButtonRef = useRef(null)
const [isSubmitting, setIsSubmitting] = useState(false)
const [docsResults, setDocsResults] = useState<Page[]>([])
Expand Down Expand Up @@ -317,7 +334,7 @@ export const SupportFormV2 = ({

useEffect(() => {
if (urlCategory) {
const validCategory = CATEGORY_OPTIONS.find((option) => {
const validCategory = categoryOptions.find((option) => {
if (option.value.toLowerCase() === ((urlCategory as string) ?? '').toLowerCase())
return option
})
Expand Down Expand Up @@ -533,13 +550,13 @@ export const SupportFormV2 = ({
<SelectTrigger_Shadcn_ className="w-full">
<SelectValue_Shadcn_ placeholder="Select an issue">
{field.value
? CATEGORY_OPTIONS.find((o) => o.value === field.value)?.label
? categoryOptions.find((o) => o.value === field.value)?.label
: null}
</SelectValue_Shadcn_>
</SelectTrigger_Shadcn_>
<SelectContent_Shadcn_>
<SelectGroup_Shadcn_>
{CATEGORY_OPTIONS.map((option) => (
{categoryOptions.map((option) => (
<SelectItem_Shadcn_ key={option.value} value={option.value}>
{option.label}
<span className="block text-xs text-foreground-lighter">
Expand Down
Loading
Loading