Files
supabase/apps/studio/components/interfaces/Database/Replication/PublicationsComboBox.tsx
Raminder Singh 23ceb9072d Add replication UI in Studio (#30090)
* add dummy sinks and pipelines pages

* update api types

* show empty sources state

* show empty replication state at /replication

* create source when enable replication button is clicked

* improve replication page when replication is enabled

* replace sources page with publications page

* publications table

* show publications in table

* create publication wip

* show toast error instead of throwing an exception

* user can now delete a publication

* show empty sinks page

* create and list sinks

* add ui to delete a sink

* show pipelines on the pipelines page

* add ui to create and delete pipelines

* get pipeline status wip

* show pipeline status wip

* show correct label on action buttons

* start and stop pipelines

* remove a couple of console.logs

* fix error when deleting a pipeline

* only consider replication enabled when a source with name = ref is present

* add source and sink names

* correct colspan for 'no pipelines' row

* hide 'supabase_realtime' publication on ui

* move filtering to fetch query

* show sink name in ui

* show source/sink names on pipelines page

* fix start/stop status shown on ui

* fix prettier formatting

* update api types

* extract pipeline action button as a separate component

* fix a crashing page

* fixed publications page crash

* update to match with changes in api

* add new replication page under database

* hide replication page behind feature flag

* update types

* update api types

* show destinations empty state

* add destinations table

* factor out components from Destinations table

* show status dot

* move pipeline fetch query to parent component

* add ability to enable/disable a pipeline

* show loader when starting or stopping a pipeline

* fix a bug in which loading & empty states were shown together

* fix a bug in which error & empty states were shown together

* wrap in default layout

* add new destination panel

* add type field

* fix a forwardRef error

* fix layout

* create destination

* delete destination

* add ability to create or delete destinations with pipelines

* create source if missing

* show only a single error

* add an enable switch

* new layout

* add subsections

* comment out unused code

* show enabled switch only in the header

* close panel when destination is created

* disable buttons when api requests in flight

* reduce panel size

* remove commented out code

* treat max size and max fill secs as numbers

* use drop down to show publications

* simpler vertical layout

* add separators

* add form validation

* remove publications drop down padding

* add new publication button

* hide advanced settings behind an accordion

* add some margin between icon and text

* show publications panel on clicking new publication button

* add header to new publication panel

* fix validation not running for publication drop down

* create publication in the new publication panel

* add table selector in new publication panel

* update api types

* remove old code

* update platform.d.ts

* update navigation bar utils

* remove a redirect from replication page to publications page

* ask user for confirmation before deleting destination

* edit destination panel

* edit destination panel values fixed

* bug fixes

* fix prettier formatting

* enable/disable pipeline after editing

* rename snake_case params to camelCase

* loading button when editing

* remove merge markers

* update api types

* add max_staleness parameter in sinks for bigquery

* add read replicas flow diagram to replication page

* remove an unused import

* Revert "add read replicas flow diagram to replication page"

This reverts commit 8852d7847b457885603dba786141a8aaf8e99350.

* add panel to warn users about additional cost before creating a destination

* hide replication page contents behind a feature flag

* fix merge conflicts

* styling changes

* revert static flag

* styling updates

* fixes

* fix switch

* copy

* fix layout

---------

Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com>
2025-04-23 10:52:46 +05:30

133 lines
4.0 KiB
TypeScript

import { Check, ChevronsUpDown, Loader2, Plus } from 'lucide-react'
import { useState } from 'react'
import {
Button,
Command_Shadcn_,
CommandEmpty_Shadcn_,
CommandGroup_Shadcn_,
CommandInput_Shadcn_,
CommandItem_Shadcn_,
CommandList_Shadcn_,
CommandSeparator_Shadcn_,
Popover_Shadcn_,
PopoverContent_Shadcn_,
PopoverTrigger_Shadcn_,
ScrollArea,
} from 'ui'
import { ControllerRenderProps } from 'react-hook-form'
interface PublicationsComboBoxProps {
publications: string[]
loading: boolean
onNewPublicationClick: () => void
field: ControllerRenderProps<any, 'publicationName'>
}
const PublicationsComboBox = ({
publications,
loading,
onNewPublicationClick,
field,
}: PublicationsComboBoxProps) => {
const [dropdownOpen, setDropdownOpen] = useState(false)
const [selectedPublication, setSelectedPublication] = useState<string>(field?.value || '')
const [searchTerm, setSearchTerm] = useState('')
function handleSearchChange(value: string) {
setSearchTerm(value)
}
function handlePublicationSelect(pub: string) {
setSelectedPublication(pub)
setDropdownOpen(false)
field.onChange(pub)
}
return (
<Popover_Shadcn_
modal={false}
open={dropdownOpen}
onOpenChange={(open) => {
setDropdownOpen(open)
if (!open && field?.onBlur) {
field.onBlur()
}
}}
>
<PopoverTrigger_Shadcn_ asChild>
<Button
type="default"
size="medium"
className={`w-full [&>span]:w-full text-left`}
iconRight={
<ChevronsUpDown
className="text-foreground-muted"
strokeWidth={2}
size={14}
></ChevronsUpDown>
}
name={field.name}
onBlur={field.onBlur}
>
{selectedPublication || 'Select publication'}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0" sameWidthAsTrigger>
<Command_Shadcn_>
<CommandInput_Shadcn_
placeholder="Find publication..."
value={searchTerm}
onValueChange={handleSearchChange}
></CommandInput_Shadcn_>
<CommandList_Shadcn_>
<CommandEmpty_Shadcn_>
{loading ? (
<div className="flex items-center gap-2 text-center justify-center">
<Loader2 size={12} className="animate-spin" />
Loading...
</div>
) : (
'No publications found'
)}
</CommandEmpty_Shadcn_>
<CommandGroup_Shadcn_>
<ScrollArea className={publications.length > 7 ? 'h-[210px]' : ''}>
{publications.map((pub) => (
<CommandItem_Shadcn_
key={pub}
className="cursor-pointer flex items-center justify-between space-x-2 w-full"
onSelect={() => {
handlePublicationSelect(pub)
}}
onClick={() => {
handlePublicationSelect(pub)
}}
>
<span>{pub}</span>
{selectedPublication === pub && (
<Check className="text-brand" strokeWidth={2} size={13} />
)}
</CommandItem_Shadcn_>
))}
</ScrollArea>
</CommandGroup_Shadcn_>
<CommandSeparator_Shadcn_ />
<CommandGroup_Shadcn_>
<CommandItem_Shadcn_
className="cursor-pointer w-full"
onSelect={onNewPublicationClick}
onClick={onNewPublicationClick}
>
<Plus size={14} strokeWidth={1.5} className="mr-2" />
<p>New publication</p>
</CommandItem_Shadcn_>
</CommandGroup_Shadcn_>
</CommandList_Shadcn_>
</Command_Shadcn_>
</PopoverContent_Shadcn_>
</Popover_Shadcn_>
)
}
export default PublicationsComboBox